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);
}
}
答案 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
您可以看到BIPUSH
将20
压入堆栈,然后ISTORE
将该值存储到本地变量中。
这是一个Fernflower
问题。
出于您的兴趣,字节码版本55
的输出为
int VAL = true;
System.out.println(20);
您可以看到反编译器可能是错误的:)
答案 1 :(得分:1)
潜在的问题是Java字节码没有布尔值,字节,字符或短裤(类型签名除外)的概念。所有具有这些类型的局部变量都将编译为ints。布尔值true和false分别编译为1
和0
。
这意味着反编译器必须猜测给定的局部变量是布尔型还是整数型。在这种情况下,值20
存储在变量中,而该变量将永远不会存储在Java代码中的布尔型变量中,因此反编译器应该容易地猜测它是基于以下类型的整数类型:上下文。但是看来Fernflower的布尔猜测器并不那么复杂。
就其价值而言,这是一个固有的难题。特别是当您考虑到非Java字节码不必遵循Java相同的模式时。字节码在整数和布尔上下文中使用相同的变量是完全有效的。 The Krakatau decompiler有一个相当复杂的推断步骤,可以猜测变量是否应该为布尔值,但是在这种情况下仍然会出错。
答案 2 :(得分:0)
就像compiler
在optimization
的生成过程中做一些byte code
一样。当VAL = 20时;是最终的并且没有变化,因此可以在第二条语句中将20
替换为VAL
,而没有impacting
的功能。现在decompiler
只有byte code
,当它去读取字节码时,发现20
是second 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