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

Posted by '김용환'
,