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