scala 코드가 어떻게 jvm에서 인식될 수 있는 지 확인하려면 세 가지 방법이 있다.
1. jad
2. javap
3. scalac -print
1.jad
jad는 scalac 자바 class 화일을 java로 역어셈블링한다. 간단한 파일은 scalac -print로 테스트해볼 수 있지만, scalac 파일이 많아지면 너무 많아진다. 필요한 것만 보기에 좋다.
$ scalac Main.java
$ jad *.class
$ls *
Main$.class Main.class Price$.class Price.jad Printable.jad
Main$.jad Main.jad Price$.jad Printable$class.class
Main$delayedInit$body.class Main.scala Price.class Printable.class
클래스 파일을 에디터로 다음처럼 살펴보면 된다.
$ vi Price.jad
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: Main.scala
import scala.*;
import scala.collection.Iterator;
public final class Price
implements Printable, Product, Serializable
{
public static String toString$extension(int i)
{
return Price$.MODULE$.toString$extension(i);
...
2. javap
JDK 툴을 사용해서 jvm languague를 살펴본다.
$ scalac Main.java
$ javap -c Price
(만약 private 메소드를 보려면, -private을 추가한다. $ javap -c -private Price)
Compiled from "Main.scala"
public final class Price implements Printable,scala.Product,scala.Serializable {
public static java.lang.String toString$extension(int);
Code:
0: getstatic #22 // Field Price$.MODULE$:LPrice$;
3: iload_0
4: invokevirtual #24 // Method Price$.toString$extension:(I)Ljava/lang/String;
7: areturn
3. scalac -print
java 기반이 아닌 scala식 역어셈블링이다.
관련된 코드가 예쁘게 모두 나온다. 너무 많은 클래스를 컴파일 할 때는 너무 많이 나올 수 있다.
$ scalac -print Main.scala
[[syntax trees at end of cleanup]] // Main.scala
package <empty> {
abstract trait Printable extends Object {
def print(): Unit
};
final case class Price extends Object with Printable with Product with Serializable {
def print(): Unit = Printable$class.print(Price.this);
<caseaccessor> <paramaccessor> private[this] val price: Int = _;
<stable> <caseaccessor> <accessor> <paramaccessor> def price(): Int = Price.this.price;
<synthetic> def copy(price: Int): Int = Price.copy$extension(Price.this.price(), price);
<synthetic> def copy$default$1(): Int = Price.copy$default$1$extension(Price.this.price());
override <synthetic> def productPrefix(): String = Price.productPrefix$extension(Price.this.price());
<synthetic> def productArity(): Int = Price.productArity$extension(Price.this.price());
<synthetic> def productElement(x$1: Int): Object = Price.productElement$extension(Price.this.price(), x$1);
override <synthetic> def productIterator(): Iterator = Price.productIterator$extension(Price.this.price());
<synthetic> def canEqual(x$1: Object): Boolean = Price.canEqual$extension(Price.this.price(), x$1);
override <synthetic> def hashCode(): Int = Price.hashCode$extension(Price.this.price());
override <synthetic> def equals(x$1: Object): Boolean = Price.equals$extension(Price.this.price(), x$1);
override <synthetic> def toString(): String = Price.toString$extension(Price.this.price());
def <init>(price: Int): Price = {
Price.this.price = price;
Price.super.<init>();
Printable$class./*Printable$class*/$init$(Price.this);
scala.Product$class./*Product$class*/$init$(Pr