如果JVM在执行GC时保持移动对象,它如何解析引用? [英] If the JVM keeps moving objects around when it does GC, how does it resolve references?

查看:279
本文介绍了如果JVM在执行GC时保持移动对象,它如何解析引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读JVM调优,而我发现JVM在执行GC时会移动对象。但是Java对象之间有相互引用,哪一个可以假定为指针,但是JVM在每次移动对象后都不可能遍历整个堆,并且更新所有引用;当然,这将永远需要。那么如何解决引用问题,如果引用没有改变,但是这些对象的物理位置呢?



我已经读了很多关于JVM的内容,但是在任何地方都没有解释,甚至暗示。



我的观点是引用是单向的。从指针指向指针是瞬间的,但反过来需要全面扫描。虽然这是可能的,但似乎不太可能。如果10K对象在小集合中存活,则需要多长时间才能完成10K次全堆扫描以更新对这些对象的引用?如果你真的对垃圾收集器是如何工作的感兴趣,我可以吗?我可以吗?推荐理查德琼斯关于垃圾收集的两本书。链接/引用此处。这不是关于Java垃圾回收的具体问题。



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






以下是复制收集器处理此问题的简单版本。复制收藏夹通过将对象从一个空间(from-space)复制到另一个空间(to-space)来工作。



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




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


    1. 它将空间中的对象标记出来。

    2. 它将对象复制到空间中。
    3. 它存储地址该对象将进入从空间对象中的空间。 (这就像转发地址。)

    4. 递归访问对象的空间副本的每个引用字段。

    这是对空对象的引用的结果。


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




位置(位于空间或某个GC根目录)如果你遵循所有这些,那么你将会看到GC中的引用被更新为指向空间中的对象的指针。



不需要去寻找所有的地方举行一个给定的移动对象的引用。相反,它只是遇到遍历可达对象的所有地方。当然,GC 确实不得不做这种遍历,但有各种技术可以减少每个GC循环中需要完成的遍历数量。



如果您没有遵循上述规定,请阅读我推荐的教科书之一。他们会比我能做的更好地解释它。您还可以找到其他类型的GC处理此问题的材料。






Java HotSpot GCs all 复制一种或另一种形式的收集器。事情比我上面描述的并行和并发收集更复杂一些,但是转发地址机制对所有这些机制都是通用的。



在HotSpot GC上发布的论文或其他公共文档,以及大多数存在的材料假设读者对现代垃圾收集器的工作原理有很好的理解。)

I'm reading on JVM tuning, and it occurred to me that the JVM keeps moving objects around when it does GC. But Java Objects have references to each other, which one would presume are implemented as pointers, but the JVM can't possibly go over the whole heap after every time it moved objects around, and update all the references; surely that would take for ever. So how does it resolve references, if the references do not change, but the physical location of the objects do?

I've read a lot about the JVM, but that was never explained, or even hinted at, anywhere.

[EDIT] My point is that references are one-way things. Going from the pointer to the pointed is "instantaneous", but going the other way around would require a full heap scan. While it is possible, it seems unlikely. If 10K objects survive a minor collection, how long would it take to do a full heap scan 10K times to update the references to those objects? There must be some kind of optimized algorithm or structure used.

解决方案

If you are really interested in how garbage collectors work, can I recommend Richard Jones' 2 books on Garbage Collection. Links / references are here. This isn't specifically about Java garbage collection.

(I have a copy of the older book, and the new one is on my shopping list.)


Here's a simple version of how a copying collector deals with this problem.

A copying collector works by copying objects from one space (the from-space) to another one (the to-space).

Specifically, the GC walks the graph of reachable objects within the "from" space, starting from each of the GC roots. Each time it finds a reference to a node (in an instance field, static field, stack frame, etc), it checks the object that the reference points to to see if it has been marked as visited.

  • If it is not yet marked, the GC does the following:

    1. It marks the object in the from-space.
    2. It copies the object into the to-space.
    3. It stores the address of the object in to space in the from-space object. (This is like a forwarding address.)
    4. It recursively visits each reference field of the to-space copy of the object.

    The result of this the reference to the to-space object.

  • If the object has been marked already, the GC looks up the forwarding address, and returns that.

The location (in to-space, or some GC root) where the GC got the reference from is then updated with the pointer to the object in to-space.

If you follow all of that, then you will see that the GC doesn't need to go looking for all of the places that hold a reference to a given moved object. Instead, it simply encounters all of the places in the traversal of the reachable objects. Of course, the GC does have to do that traversal, but there are various techniques to reduce the amount of traversing that needs to be done in each GC cycle.

If you haven't followed the above, then PLEASE go read one of the textbooks that I've recommended. They'll do a much better job of explaining it than I can do. You'll also find material on how other kinds of GC deal with this issue.


The Java HotSpot GCs are all copying collectors of one form or another. Things get a bit more complicated than my description above for parallel and concurrent collecting, but the "forwarding address" mechanism is common to all of them.

(There are not many published papers or other public documentation on HotSpot GCs, and most of the material that exists assumes that the reader has a good understanding of how modern garbage collectors work.)

这篇关于如果JVM在执行GC时保持移动对象,它如何解析引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆