OpenJDK 1.8.0_191
我编译并解压缩了下面的一段代码,使用弗恩弗劳尔。
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中,反编译代码如下所示:
//
// 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);
}
}发布于 2019-03-08 19:17:21
字节码是
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);您可以看到反编译程序可能是错误的:)
发布于 2019-03-09 02:31:19
根本的问题是Java字节码没有布尔( booleans )、字节(字节)、字符( chars )或短裤(类型签名除外)的概念。所有具有这些类型的局部变量都被编译为ints。布尔值true和false分别编译为1和0。
这意味着反编译器必须猜测给定的局部变量是布尔型还是整数型。在这种情况下,值20存储在变量中,该变量将永远不会存储在Java代码中的布尔类型变量中,因此反编译器应该很容易猜测它是基于上下文的整数类型。但弗劳尔的布尔猜测似乎并不那么复杂。
就其价值而言,这是一个固有的难题。特别是当您考虑到非Java字节码不需要遵循与Java相同的模式时。字节码在整数和布尔上下文中使用相同的变量是完全有效的。对于猜测变量是否应该是布尔人,克拉卡托反编译器有一个相当复杂的推断步骤,但在这种情况下,它仍然会出错。
发布于 2019-03-08 19:12:01
它的工作方式就像compiler在生成byte code期间做一些optimization一样。因为VAL = 20;是最终的,并且不会更改,所以它可以将20替换为VAL,而不需要impacting第二个语句中的功能。现在,decompiler只有byte code,当它读取拜特代码时,它在second line中找到了内联的20。由代码生成的字节代码如下:
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)Vhttps://stackoverflow.com/questions/55069491
复制相似问题