Intellij Idea 为什么show bytecode和class file不匹配?

x33g5p2x  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(153)

原始.java文件

public enum Fruit {
    ORANGE(1), APPLE(2);
    private final int i;
    Fruit(int i){
        this.i=i;
    }
}

字符串

.class文件

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

public enum Fruit {
    ORANGE,
    APPLE;

    private Fruit() {
    }
}

显示字节码结果

// class version 61.0 (61)
// access flags 0x4031
// signature Ljava/lang/Enum<LFruit;>;
// declaration: Fruit extends java.lang.Enum<Fruit>
public final enum Fruit extends java/lang/Enum {

  // compiled from: Fruit.java

  // access flags 0x4019
  public final static enum LFruit; ORANGE

  // access flags 0x4019
  public final static enum LFruit; APPLE

  // access flags 0x12
  private final I i

  // access flags 0x101A
  private final static synthetic [LFruit; $VALUES

  // access flags 0x9
  public static values()[LFruit;
   L0
    LINENUMBER 1 L0
    GETSTATIC Fruit.$VALUES : [LFruit;
    INVOKEVIRTUAL [LFruit;.clone ()Ljava/lang/Object;
    CHECKCAST [LFruit;
    ARETURN
    MAXSTACK = 1
    MAXLOCALS = 0

  // access flags 0x9
  public static valueOf(Ljava/lang/String;)LFruit;
   L0
    LINENUMBER 1 L0
    LDC LFruit;.class
    ALOAD 0
    INVOKESTATIC java/lang/Enum.valueOf (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
    CHECKCAST Fruit
    ARETURN
   L1
    LOCALVARIABLE name Ljava/lang/String; L0 L1 0
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x2
  // signature (I)V
  // declaration: void <init>(int)
  private <init>(Ljava/lang/String;II)V
   L0
    LINENUMBER 4 L0
    ALOAD 0
    ALOAD 1
    ILOAD 2
    INVOKESPECIAL java/lang/Enum.<init> (Ljava/lang/String;I)V
   L1
    LINENUMBER 5 L1
    ALOAD 0
    ILOAD 3
    PUTFIELD Fruit.i : I
   L2
    LINENUMBER 6 L2
    RETURN
   L3
    LOCALVARIABLE this LFruit; L0 L3 0
    LOCALVARIABLE i I L0 L3 3
    MAXSTACK = 3
    MAXLOCALS = 4

  // access flags 0x100A
  private static synthetic $values()[LFruit;
   L0
    LINENUMBER 1 L0
    ICONST_2
    ANEWARRAY Fruit
    DUP
    ICONST_0
    GETSTATIC Fruit.ORANGE : LFruit;
    AASTORE
    DUP
    ICONST_1
    GETSTATIC Fruit.APPLE : LFruit;
    AASTORE
    ARETURN
    MAXSTACK = 4
    MAXLOCALS = 0

  // access flags 0x8
  static <clinit>()V
   L0
    LINENUMBER 2 L0
    NEW Fruit
    DUP
    LDC "ORANGE"
    ICONST_0
    ICONST_1
    INVOKESPECIAL Fruit.<init> (Ljava/lang/String;II)V
    PUTSTATIC Fruit.ORANGE : LFruit;
    NEW Fruit
    DUP
    LDC "APPLE"
    ICONST_1
    ICONST_2
    INVOKESPECIAL Fruit.<init> (Ljava/lang/String;II)V
    PUTSTATIC Fruit.APPLE : LFruit;
   L1
    LINENUMBER 1 L1
    INVOKESTATIC Fruit.$values ()[LFruit;
    PUTSTATIC Fruit.$VALUES : [LFruit;
    RETURN
    MAXSTACK = 5
    MAXLOCALS = 0
}


为什么show bytecode和class file不匹配?
我研究了如何在intellij中进行反编译过程,但我找不到任何官方参考。
我相信show bytecode的结果不是原始的Bytecode。这是因为原始的Bytecode不是人类可读的。
所以,作为Show bytecode的结果,类文件的反编译版本都是经过处理的形式。为什么两者之间会有差异呢?
(我也听说类文件是由字节码组成的)
这是由反编译过程和show bytecode过程之间的差异引起的问题吗?后者更有弹性?(猜测)

inb24sb2

inb24sb21#

为什么两者之间存在差异?
如果你问为什么“.class file”和“show bytecode result”之间存在差异,那是因为它们显示的是不同的东西:

  • 前者显示反编译器试图从字节码重构源代码。
  • 后者展示了字节码的反汇编;即,字节码呈现为(近似于)字节码汇编语言。这是为那些希望在JVM规范的帮助下1读取Java编译器输出的字节码的人设计的。

如果你问为什么“原始.java文件”和“.class文件”是不同的,它们(再一次)显示了不同的东西。

  • 前者显示您编写的Java源代码
  • 后者显示的是由反编译器生成的 * 重构 * Java代码。基本上,原始代码被编译成字节码,然后被 * 反编译 * 回Java源代码。这些代码可能正确,也可能不正确2。

在这种情况下,反编译代码与原始代码不同。看起来反编译器无法重建enum及其private int变量的构造函数。这是Intellij使用的反编译器的一个 * 限制 *。我想这个限制 * 可以 * 修复3。然而反编译器的限制是固有的,无法修复。这些限制包括:

  • 反编译器无法重构原始代码布局、javadoc、注解等“.class”文件中不存在的内容。
  • 如果两个不同的Java源代码构造编译为相同的字节码,反编译器无法分辨最初使用的是哪一个。
  • 字节码混淆器,故意对字节码做一些事情,使其更难重构有效的Java源代码......更不用说可读的代码了。

1 -这并不像你想象的那么有用。“问题”是字节码是(故意)不优化。相反,JIT编译器将(最终)编译并优化字节码为本地代码。通常JIT编译器执行的转换是相当激进的;例如内联方法,优化掉不必要的循环,这意味着您可能从阅读字节码中获得的所谓性能洞察(充其量)是不可靠的。
2 -它可能与原始代码在功能上不完全相同。实际上,它甚至可能不是有效的Java源代码。这有各种原因。
3 -...如果有人愿意投入工作。事实上,这个问题有可能已经在(假设的)更新版本的反编译器中得到了解决。

b4wnujal

b4wnujal2#

正如FernFlower的评论所解释的,你所指的.class文件实际上是重新创建的源代码。.class文件通过反编译器运行,试图将字节码转换回其原始源代码。
您粘贴的“show bytecode result”代码只是文件内容的可读表示

相关问题