Oracle和Eclipse编译器生成的java字节码的差异
我们的项目执行一些Java字节码检测。 我们偶然发现了一些奇怪的行为。 假设以下代码段:
public void a() { new Integer(2); }
Oracle的javac将上面的代码编译成以下字节码:
0: new #2; //class java/lang/Integer 3: dup 4: iconst_2 5: invokespecial #3; //Method java/lang/Integer."":(I)V 8: pop 9: return
和Eclipse的编译器进入:
0: new #15; //class java/lang/Integer 3: iconst_2 4: invokespecial #17; //Method java/lang/Integer."":(I)V 7: return
如您所见,Oracle编译器在“new”之后生成“dup”,而Eclipse则不然。 在这个用例中完全正确,因为根本不使用新创建的Integer实例,因此不需要“dup”。
我的问题是:
- 是否对不同编译器之间的差异有一些概述? 文章/博文?
- 我可以安全地得出结论,如果“new”和“invokespecial”之间没有“dup”,那么在初始化之后不会使用对象吗?
- 我可以安全地得出结论,如果“new”和“invokespecial”之间没有“dup”,那么在初始化之后不会使用对象吗?
我不确定你的意思,但是对于创建的对象的引用可能会被构造函数存储在某处。 因此,调用方法可能在初始化后不使用该对象,但该对象可能仍然可以访问,因此可能不是垃圾可收集的。
如果new和invokespecial之间存在重复,则通常在编译后使用该对象。 例如,字段初始化通常是new , dup , invokespecial和putfield的序列。 但是,在您的示例中,最后一条指令是pop ,它清除堆栈中的objectref – 这就是您可以假设不使用此对象的方式。
通过此引用将打破这种模式
public class Bump { Test t; public Bump() { new Test(this); } public void setT(Test t) { this.t = t; } }
然后可以使用它来存储结果:)
public class Test { Bump b; public Test(Bump b) { this.b = b; b.setT(this); } }
玩的开心 :)