如果JVM在执行GC时一直在移动对象,那么它如何解析引用?

我正在阅读JVM调优,我发现JVM在执行GC时会不断移动对象。但是Java对象之间有相互引用,可以假定它们是作为指针实现的,但是JVM每次移动对象并更新所有引用后,都不可能遍历整个堆。当然,这将永远。那么,如果引用不变,但对象的物理位置却发生变化,它将如何解析引用?

我已经阅读了很多有关JVM的文章,但是从来没有在任何地方解释甚至暗示过它。

[编辑]我的观点是引用是单向的。从指针到指针是“瞬时”的,但是从另一方向走则需要完整的堆扫描。虽然有可能,但似乎不太可能。如果10K个对象在次要收集中幸存下来,则进行全堆扫描10K次以更新对这些对象的引用需要花费多长时间?必须使用某种优化的算法或结构。

回答:

如果您真的对垃圾收集器的工作方式感兴趣,我可以推荐理查德·琼斯的两本有关垃圾收集的书。链接/参考在这里。这不是专门关于Java垃圾收集的。

(我有一本旧书的副本,而新书在我的购物清单上。)


这是复制收集器如何处理此问题的简单版本。

复制收集器通过将对象从一个空间(“从”空间)复制到另一个空间(“到”空间)来工作。

具体来说,GC从每个GC根开始,在“从”空间内遍历可访问对象的图形。每次找到对节点的引用(在实例字段,静态字段,堆栈框架等中)时,它都会检查该引用指向的对象,以查看其是否已标记为已访问。

  • 如果尚未标记,GC将执行以下操作:

    1. 它在起始空间中标记对象。
    2. 它将对象复制到目标空间。
    3. 它将对象的地址存储到起始空间对象中的空间中。(这就像一个转发地址。)
    4. 它递归地访问对象的空间副本的每个参考字段。

其结果是引用到空间对象。

  • 如果该对象已被标记,GC将查找转发地址,并返回该地址。

然后,使用指向to-space中对象的指针来更新GC引用来源的位置(在to-space或某个GC根目录中)。

如果您遵循所有这些方法,那么您将发现GC不需要去寻找所有拥有对给定移动对象的引用的位置。相反,它仅遇到遍历可到达对象的所有位置。当然,GC 确实

必须进行遍历,但是有各种技术可以减少每个GC循环中需要进行的遍历量。

如果您未遵循上述说明,请阅读我推荐的其中一本教科书。他们会比我做得更好。您还将找到有关其他种类的GC如何处理此问题的材料。


虽然Java HotSpot的GC是 所有

这种或那种形式的复制。对于并行和并发收集,事情要比我上面的描述要复杂得多,但是“转发地址”机制对所有它们都是通用的。

(关于HotSpot GC的出版物或其他公共文档并不多,并且现有的大多数材料都假定读者对现代垃圾收集器的工作原理有很好的了解。)

以上是 如果JVM在执行GC时一直在移动对象,那么它如何解析引用? 的全部内容, 来源链接: utcz.com/qa/413186.html

回到顶部