在 Java VM 中,如何处理对象引用
在 Java 应用程序的执行过程中,对象引用是由运行时使用还是在编译时删除?
我想我可以反编译类文件,看看它们是如何用作局部变量和成员变量的。
当您不需要时创建对象引用是否浪费,或者编译器会删除不需要的引用?
例如
最终字符串 abc = "abc"; 方法(abc);
与:
method("abc");相反
During the execution of a Java application, are object references used by the runtime or are they stripped away at compile time?
I guess I could decompile class files and see how they are used as local variables and member variables.
Is it wasteful to create an object reference when you don't need to or will the compiler strip away unneeded references?
E.g.
final String abc = "abc";
method(abc);
as opposed to:
method("abc");
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
方法存储在对象数据区域(如类定义所示),但块本地引用存储在 JVM 堆栈帧的特殊区域中。当帧从执行线程的帧堆栈中弹出时,所有块本地引用都会丢失,因为它们实际上并未存储在对象的数据结构中。
请注意,如果您不熟悉 JVM 堆栈帧,则在进入每个方法时都会获得一个新的堆栈帧,并在从方法返回时从线程堆栈中弹出。堆栈帧包含许多元素,包括指向当前指令(位于类的指令页中)的指针、指向“this”对象的指针,以及用于保存当前方法计算中的中间体的小堆栈。有时,变量引用不需要任何存储,并且许多优化编译器将编译代码以使用本地堆栈而不是“对象引用存储”,这意味着逆向代码将导致无法发现该人根本使用了一个变量。
“this”指针始终占据对象引用存储区域的第一个条目,所有这些概念都是概念性的。实际的实现只需要符合操作标准,不需要符合特定的内存布局。
Methods are stored in the object data area (as laid out by the class definition), but block local references are stored in a special area of the JVM stack frame. When the frame pops off of the frame stack of the executing thread, all the block local references are lost as they are not actually stored in the object's data structures.
Note that if you are unfamiliar with JVM stack frames, a new stack frame is obtained for the entry into every method, and is popped off the Thread's stack when returning from a method. Stack frames contain a number of elements, including a pointer to the current instruction (which is located in the Class's instruction pages) a pointer to the "this" object, and a small stack to hold intermediates in the current method calculation. Sometimes a variable reference doesn't incur any need for storage, and many optimizing compilers will then compile out the code to use the local stack instead of the "object reference storage" meaning that reversing of the code will result in not discovering that the person used a variable at all.
The "this" pointer always occupies the first entry in the object reference storage area, and all of these concepts are conceptual. The actual implementation only needs to conform to the operational standard, it doesn't need to conform to a particular memory layout.
在字节码级别,像这样的“不必要的”引用不会被删除;你可以在字节码中看到上面的赋值。但 JIT(即 HotSpot)通常更加智能,因此运行时影响基本上为零。
At the bytecode level, "unnecessary" references like this will not be stripped out; you could see the above assignment in the bytecode. But the JIT (i.e., HotSpot) is generally much smarter, and so the runtime impact is essentially zero.
在您提到的特定情况下,您命名一个局部变量并将其称为“abc”这一事实对于您作为程序员来说本质上是一种方便。无论您是否这样做或只是将其保留为未命名参数,字节码本质上都会是相同的。
一般来说,您不需要担心这种程度的细节。您可以相信字节码编译器和 JIT 编译器会做明智的事情。如果你必须担心到这种程度的细节,那么几乎不可能编写任何中等复杂度的应用程序......
[PS如果你有时间和兴趣,我还建议你反编译相应的类,就像一项教育活动。但你会发现应该非常令人放心:编译器正在做通常明智的事情,没有必要偏执。]
In the particular case you mention, the fact that you name a local variable and call it "abc" is essentially a convenience for you as the programmer. Whether or not you do so or just leave it as an unnamed parameter, the bytecode will essentially end up the same.
In general, you don't need to worry about that level of detail. You can trust the bytecode compiler and JIT compiler to do sensible things. If you had to worry down to this level of detail, it would be practically impossible to write any application of moderate complexity...
[P.S. If you have the time and interest, I would also recommend that you do decompile the corresponding classes just as an educational exercise. But what you will find should be quite reassuring: that the compiler is doing generally sensible things and there's no need to be paranoid.]