Java 8 / Fernflower Decompiler:错误或功能

问题描述 投票:0回答:3

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);
    }
}
java decompiling decompiler
3个回答
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
投票

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

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

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


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
© www.soinside.com 2019 - 2024. All rights reserved.