我正在调查JVM架构及其在幕后的工作。
我听过很多次堆栈存储方法的返回类型,操作数,局部变量和对象的引用。
但是在阅读Oracle规范时,我发现绘制的图片表示堆栈帧没有直接引用对象,而是引用常量池。
我是否正确理解堆栈是否具有对堆中对象的引用的引用?
框架 - 是堆栈的一部分。
每个帧都有自己的局部变量数组(第2.6.1节) 操作数堆栈(第2.6.2节),以及对运行时常量池的引用 (§2.5.5)当前方法的类。
从这个解释中我可以理解,为了在堆中获取对象的地址,我们需要在运行时常量池中找到它。
链接到Oracle规范 - https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html
答案 0 :(得分:-3)
Stack可以包含指向堆和常量池的指针(顺便说一下,这也是符合JVM规范的堆中的逻辑)。具体实现这些指针可以指向对象或指向对象的指针。
垃圾收集器的实现可以影响这种行为。例如,Shenandoah Gc使用附加指针来访问对象(*)。通过此实现,堆栈中的指针(gc root)指向指向实际对象的另一个指针。 Oracle Jvm没有像这样实现。
(*)实施细节;
在垃圾回收期间,堆中的对象可以移动到不同的内存位置。例如,伊甸园空间中的物体可以移动到幸存者空间,然后移动到老一代。 使用此信息,假设一个对象由10个指针指向,如果该对象的存储器地址被更改,则应更新10个指针以指向正确的地址。如果指针指向转发指针,那转发指针指向对象;这次只需要更新转发指针。转发指针方法的目的是减少垃圾收集暂停时间(以较低的吞吐量为代价)
以下视频中有对此过程的解释。
https://youtu.be/AAiB3fDwyRM?t=424
https://wiki.openjdk.java.net/display/shenandoah/Main https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.4