原始.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过程之间的差异引起的问题吗?后者更有弹性?(猜测)
2条答案
按热度按时间inb24sb21#
为什么两者之间存在差异?
如果你问为什么“.class file”和“show bytecode result”之间存在差异,那是因为它们显示的是不同的东西:
如果你问为什么“原始.java文件”和“.class文件”是不同的,它们(再一次)显示了不同的东西。
在这种情况下,反编译代码与原始代码不同。看起来反编译器无法重建
enum
及其private int
变量的构造函数。这是Intellij使用的反编译器的一个 * 限制 *。我想这个限制 * 可以 * 修复3。然而反编译器的限制是固有的,无法修复。这些限制包括:1 -这并不像你想象的那么有用。“问题”是字节码是(故意)不优化。相反,JIT编译器将(最终)编译并优化字节码为本地代码。通常JIT编译器执行的转换是相当激进的;例如内联方法,优化掉不必要的循环,这意味着您可能从阅读字节码中获得的所谓性能洞察(充其量)是不可靠的。
2 -它可能与原始代码在功能上不完全相同。实际上,它甚至可能不是有效的Java源代码。这有各种原因。
3 -...如果有人愿意投入工作。事实上,这个问题有可能已经在(假设的)更新版本的反编译器中得到了解决。
b4wnujal2#
正如FernFlower的评论所解释的,你所指的
.class
文件实际上是重新创建的源代码。.class
文件通过反编译器运行,试图将字节码转换回其原始源代码。您粘贴的“show bytecode result”代码只是文件内容的可读表示