Java 8 / Fernflower反编译器:错误或功能

时间:2019-03-08 19:07:30

标签: java decompiling decompiler

OpenJDK 1.8.0_191

我使用Fernflower编译并反编译了一段代码。

public class Decompile {
    public static void main(String[] args) {
        final int VAL = 20;
        System.out.println(VAL);
    }
}

输出为:

public class Decompile {

   public static void main(String[] args) {
      boolean VAL = true;
      System.out.println(20);
   }
}

我很困惑,VAL是怎么变成布尔值的?

更新:

在Intellij IDEA中,反编译的代码如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

public class Decompile {
    public Decompile() {
    }

    public static void main(String[] args) {
        int VAL = true;
        System.out.println(20);
    }
}

3 个答案:

答案 0 :(得分:2)

字节码是

L0
 LINENUMBER 5 L0
 BIPUSH 20
 ISTORE 1
L1
 LINENUMBER 6 L1
 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
 BIPUSH 20
 INVOKEVIRTUAL java/io/PrintStream.println (I)V

您可以看到BIPUSH20压入堆栈,然后ISTORE将该值存储到本地变量中。

这是一个Fernflower问题。


出于您的兴趣,字节码版本55的输出为

int VAL = true;
System.out.println(20);

您可以看到反编译器可能是错误的:)

答案 1 :(得分:1)

潜在的问题是Java字节码没有布尔值,字节,字符或短裤(类型签名除外)的概念。所有具有这些类型的局部变量都将编译为ints。布尔值true和false分别编译为10

这意味着反编译器必须猜测给定的局部变量是布尔型还是整数型。在这种情况下,值20存储在变量中,而该变量将永远不会存储在Java代码中的布尔型变量中,因此反编译器应该容易地猜测它是基于以下类型的整数类型:上下文。但是看来Fernflower的布尔猜测器并不那么复杂。

就其价值而言,这是一个固有的难题。特别是当您考虑到非Java字节码不必遵循Java相同的模式时。字节码在整数和布尔上下文中使用相同的变量是完全有效的。 The Krakatau decompiler有一个相当复杂的推断步骤,可以猜测变量是否应该为布尔值,但是在这种情况下仍然会出错。

答案 2 :(得分:0)

就像compileroptimization的生成过程中做一些byte code一样。当VAL = 20时;是最终的并且没有变化,因此可以在第二条语句中将20替换为VAL,而没有impacting的功能。现在decompiler只有byte code,当它去读取字节码时,发现20second line中的内联。字节码由以下代码生成:

   0: bipush        20
   2: istore_1
   3: getstatic     #20                 // Field java/lang/System.out:Ljava/io/PrintStream;
   6: bipush        20
   8: invokevirtual #26                 // Method java/io/PrintStream.println:(I)V