问题描述
我正在阅读有关 JVM 调优的文章,我突然想到 JVM 在执行 GC 时会不断移动对象.但是 Java 对象之间存在相互引用,人们会认为这是作为指针实现的,但是 JVM 不可能在每次移动对象后遍历整个堆,并更新所有引用;这肯定会永远持续下去.那么,如果引用没有改变,但对象的物理位置发生了变化,它如何解析引用呢?
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?
我已经阅读了很多关于 JVM 的文章,但从未在任何地方解释过,甚至没有暗示过.
I've read a lot about the JVM, but that was never explained, or even hinted at, anywhere.
我的意思是引用是单向的.从指针指向指向是瞬时的",但反过来需要完整的堆扫描.虽然有可能,但似乎不太可能.如果 10K 对象在一次次要收集中幸存下来,那么进行 10K 次全堆扫描以更新对这些对象的引用需要多长时间?必须使用某种优化的算法或结构.
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.
推荐答案
如果你真的对垃圾收集器的工作原理感兴趣,我可以推荐 Richard Jones 的两本关于垃圾收集的书.链接/参考是 这里.这不是专门针对 Java 垃圾回收的.
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).
具体来说,GC 从每个 GC 根开始遍历from"空间内的可达对象图.每次找到对节点的引用(在实例字段、静态字段、堆栈帧等中)时,它都会检查该引用指向的对象是否已被标记为已访问.
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.
如果尚未标记,GC 会执行以下操作:
If it is not yet marked, the GC does the following:
- 它在起始空间中标记对象.
- 它将对象复制到目标空间中.
- 它将对象的地址存储到空间对象的空间中.(这就像一个转发地址.)
- 它递归地访问对象的 to-space 副本的每个引用字段.
这个对空间对象的引用的结果.
The result of this the reference to the to-space object.
如果对象已经被标记,GC会查找转发地址,并返回.
If the object has been marked already, the GC looks up the forwarding address, and returns that.
然后用指向空间中对象的指针更新 GC 获取引用的位置(在 to-space 或某个 GC 根中).
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.
如果您遵循所有这些,那么您将看到 GC 不需要去寻找所有持有对给定移动对象的引用的位置.相反,它只是遇到可到达对象的遍历中的所有位置.当然,GC确实必须进行这种遍历,但是有多种技术可以减少每个 GC 循环中需要完成的遍历量.
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.
如果您还没有遵循上述内容,请阅读我推荐的一本教科书.他们会比我做得更好.您还可以找到有关其他类型的 GC 如何处理此问题的资料.
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.
Java HotSpot GC 是所有一种或另一种形式的复制收集器.对于并行和并发收集,事情比我上面描述的要复杂一些,但是转发地址"机制对所有这些都是通用的.
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.
(关于 HotSpot GC 的已发表论文或其他公开文档并不多,并且现有的大多数材料都假设读者对现代垃圾收集器的工作方式有很好的理解.)
(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 时不断移动对象,它如何解析引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!