CFR で Java 8 のラムダ式をデコンパイルする

Java 8 のラムダ式にも対応した CFR という Java のデコンパイラをご紹介します。

使い方

使い方は簡単で、http://www.benf.org/other/cfr/ から JAR ファイルをダウンロードして下記のように実行するだけです。

java -jar cfr_0_78.jar <Java クラスファイル> [メソッド名] [オプション]
java -jar cfr_0_78.jar <JAR ファイル> [オプション]

ラムダ式デコンパイル

それでは、下記ソースをコンパイルして出来た LambdaSample.class を CFR でデコンパイルしてみます。

LambdaSample.java
import java.util.function.Predicate;

class LambdaSample {
    public static void main(String... args) {
        Predicate<Integer> f = (x) -> x > 10;

        System.out.println("5 : " + f.test(5));
        System.out.println("15 : " + f.test(15));
    }
}

まずは、オプションを全く指定せずにデコンパイルしてみます。 ラムダ式の部分も見事にデコンパイルされたソースコードが標準出力に出力されます。

デコンパイル結果(オプション指定なし)
> java -jar cfr_0_78.jar LambdaSample.class

/*
 * Decompiled with CFR 0_78.
 */
import java.io.PrintStream;
import java.util.function.Predicate;

class LambdaSample {
    LambdaSample() {
    }

    public static /* varargs */ void main(String ... arrstring) {
        Predicate<Integer> predicate = n -> n > 10;
        System.out.println("5 : " + predicate.test(5));
        System.out.println("15 : " + predicate.test(15));
    }
}

次に、--decodelambdas false オプションを指定してラムダ式の部分をデコンパイルしないようにしてみます。

こうする事で、ラムダ式へ展開されず synthetic のメソッド定義 (ラムダ式の実体)と LambdaMetafactory.metafactory() 呼び出し処理のソースが出力されます。

デコンパイル結果(--decodelambdas false)
> java -jar cfr_0_78.jar LambdaSample.class --decodelambdas false

/*
 * Decompiled with CFR 0_78.
 */
import java.io.PrintStream;
import java.util.function.Predicate;

class LambdaSample {
    LambdaSample() {
    }

    public static /* varargs */ void main(String ... arrstring) {
        Predicate<Integer> predicate = (Predicate<Integer>)LambdaMetafactory.metafactory(null, null, null, (Ljava/lang/Object;)Z, lambda$main$0(java.lang.Integer ), (Ljava/lang/Integer;)Z)();
        System.out.println("5 : " + predicate.test(5));
        System.out.println("15 : " + predicate.test(15));
    }

    private static /* synthetic */ boolean lambda$main$0(Integer n) {
        return n > 10;
    }
}