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."<init>":(I)V
8: pop
9: return
Eclipse 的编译器将其编译为:
0: new #15; //class java/lang/Integer
3: iconst_2
4: invokespecial #17; //Method java/lang/Integer."<init>":(I)V
7: return
如您所见,Oracle 编译器在“new”之后生成“dup”,而 Eclipse 则不会。在这个用例中这是完全正确的,因为根本不使用新创建的 Integer 实例,因此不需要“dup”。
我的问题是:
- 是否有一些不同编译器之间差异的概述?文章/博客文章?
- 我可以安全地得出结论,如果“new”和“invokespecial”之间没有“dup”,那么初始化后不会使用对象吗?
Our project does some Java bytecode instrumentation. And we stumbled upon some strange behavior. Suppose the following code snippet:
public void a() {
new Integer(2);
}
Oracle's javac compiles the above into the following bytecode:
0: new #2; //class java/lang/Integer
3: dup
4: iconst_2
5: invokespecial #3; //Method java/lang/Integer."<init>":(I)V
8: pop
9: return
and Eclipse's compiler into:
0: new #15; //class java/lang/Integer
3: iconst_2
4: invokespecial #17; //Method java/lang/Integer."<init>":(I)V
7: return
As you can see, Oracle compiler produces "dup" after "new", whereas Eclipse doesn't. Which is totally correct in this use case, as newly created Integer instance is not used at all, so no "dup" is required.
My questions are:
- Is there some overview of differences between different compilers? An article/blog post?
- Can I safely conclude, that if there is no "dup" between "new" and "invokespecial" then object is not used after initialization?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果new和invokespecial之间存在dup,则该对象通常在编译后使用。例如,字段初始化通常是 new、dup、invokespecial 和 invokespecial 的序列。 普特菲尔德。但是,在您的示例中,最后一条指令是 pop ,它从堆栈中清除 objectref - 这就是您可以假设该对象未被使用的方式。
If there's a dup between new and invokespecial then the object is usually used after the compilation. For instance, field initialization is usually a sequence of new, dup, invokespecial & putfield. However, in your example the last instruction is pop which cleans the objectref from the stack - this is how you can assume that this object isn't used.
我不确定您的意思确切,但对创建的对象的引用可能会由构造函数存储在某处。因此,调用方法在初始化后可能不会使用该对象,但该对象可能仍然可达,因此可能不可进行垃圾回收。
I'm not sure what you mean exactly, but a reference to the created object might be stored somewhere by the constructor. Therefore the calling method might not use the object after initialization but the object might still be reachable and might be not garbage collectable therefore.
传递 this 引用会稍微打破这种模式
,然后可以使用 this 来存储结果:)
玩得开心:)
Passing this reference will break this pattern a bit
And then one could use this for storing the result back :)
Have fun :)