Java
Kotlin

Kotlinからコンパイルした.classファイルを逆アセンブル・逆コンパイル

このKotlinのコードにjavap(逆アセンブラ)、jad(逆コンパイラ)を使ってみる実験です。

hello.kt
fun main(args: Array<String>) {
    println("Hello, World!")
}

コードの出典
https://kotlinlang.org/docs/tutorials/command-line.html

Kotlinは他のJVM言語と同じく、Javaとして実行可能なクラスファイルにコンパイルされます。
そちらをjavapでJVMのニーモニックを表示したりjadでjavaのソースコードとして逆コンパイルすることができるので検証してみました。

コンパイル
kotlinc hello.kt -include-runtime -d hello.jar

jarを展開してhello.classに対してjavap,jadを使います

jar xf hello.jar

環境

macOS High Sierra 10

javap(逆アセンブラ)

用意

JDKに最初から入っているので不要

実行

コマンド
javap -c HelloKt.class
結果
Compiled from "hello.kt"
public final class HelloKt {
  public static final void main(java.lang.String[]);
    Code:
       0: aload_0
       1: ldc           #9                  // String args
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
       6: ldc           #17                 // String Hello, World!
       8: astore_1
       9: getstatic     #23                 // Field java/lang/System.out:Ljava/io/PrintStream;
      12: aload_1
      13: invokevirtual #29                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      16: return
}

jad(逆コンパイラ)

用意

jadの導入方法

brew tap caskroom/cask
brew install caskroom/cask/jad

参考にしたサイトhttp://inarizuuuushi.hatenablog.com/entry/2017/05/09/231600

実行

-aオプションでニーモニックをコメントとして表示できます。

コマンド
$ jad  -a HelloKt.class 
$ cat HelloKt.jad 
import java.io.PrintStream;
import kotlin.jvm.internal.Intrinsics;

public final class HelloKt
{

    public static final void main(String args[])
    {
        Intrinsics.checkParameterIsNotNull(args, "args");
    //    0    0:aload_0         
    //    1    1:ldc1            #9   <String "args">
    //    2    3:invokestatic    #15  <Method void Intrinsics.checkParameterIsNotNull(Object, String)>
        String s = "Hello, World!";
    //    3    6:ldc1            #17  <String "Hello, World!">
    //    4    8:astore_1        
        System.out.println(s);
    //    5    9:getstatic       #23  <Field PrintStream System.out>
    //    6   12:aload_1         
    //    7   13:invokevirtual   #29  <Method void PrintStream.println(Object)>
    //    8   16:return          
    }
}

結構簡単に導入・解析することができました。
今後Kotlin特有の機能がどのようにJavaとして表現・変換されているのか手元で検証しようと思います。