Java 如果我们在年轻一代身上做了标记之后就知道了所有的死物,那么为什么我们需要在老一代人身上专门搜索无法到达的对象呢?

Java 如果我们在年轻一代身上做了标记之后就知道了所有的死物,那么为什么我们需要在老一代人身上专门搜索无法到达的对象呢?,java,garbage-collection,jvm,g1gc,Java,Garbage Collection,Jvm,G1gc,我知道,在CMS和G1中,堆被划分为伊甸园、幸存者空间和老一代,唯一的区别是,在CMS中,这种划分是真实的(这些空间是连续的,位于内存的不同部分),而在G1中,它是逻辑的(堆被划分为±2000个动态区域,每个区域的大小为1到32 MB) 在这两种情况下,当满足Eden空间阈值时,开始疏散,步骤如下: 初始标记。 STW。标记应用程序的根。 同时标记。 从链接的根到对象,有从这些对象到其他对象的转换,因此实现的对象被标记为活动对象。 评论 STW。在并发标记期间创建的对象也被标记为活动(浮动垃圾)

我知道,在CMS和G1中,堆被划分为伊甸园、幸存者空间和老一代,唯一的区别是,在CMS中,这种划分是真实的(这些空间是连续的,位于内存的不同部分),而在G1中,它是逻辑的(堆被划分为±2000个动态区域,每个区域的大小为1到32 MB)

在这两种情况下,当满足Eden空间阈值时,开始疏散,步骤如下: 初始标记。 STW。标记应用程序的根。 同时标记。 从链接的根到对象,有从这些对象到其他对象的转换,因此实现的对象被标记为活动对象。 评论 STW。在并发标记期间创建的对象也被标记为活动(浮动垃圾)。 清理 最后一个阶段为即将到来的疏散阶段做好准备,计算堆区域中所有活动对象的数量,并根据预期的GC效率对这些区域进行排序

如果堆的完成达到阈值,那么混合疏散(年轻+年老)将在G1中开始。 在旧一代人中发现死亡物体是基于“记忆集”。每个区域都有一个记忆集,其中列出了从外部指向该区域的引用。这些引用被视为附加的GC根

在G1做出决定后,从老一代和年轻一代中选择哪些区域添加到集合集中


如果我们拥有所有对象的完整图形,并且在年轻疏散层上标记后知道所有活着和死去的对象,那么为什么我们需要记忆集和对旧一代中无法到达的对象的特定搜索?

记忆集(或CMS中的卡片表)背后的思想不是“在旧一代中搜索无法到达的对象”,但要快速识别旧代中的引用,需要在年轻收集期间移动活动对象时更新这些引用


疏散对象的地址已更改=>必须更新对此对象的所有传入引用。如果没有记忆集,则需要扫描整个堆以找到所有传入的引用(当然,这可能会花费太长时间)。

我只能假设您的意思是“连续”而不是“传染”。在使用来自Young g的对象之前。GC扫描整个堆以查找不可访问对象,这样就可以使用扫描结果更新引用,对吗?@Pavel否,需要标记阶段才能查找可访问对象,而不是不可访问对象。此外,年轻的GC不需要遍历整个堆,只需要收集根集和区域。但是,如果我们知道可访问,那么我们知道不可访问,是吗?@Pavel不是真的。根据定义,我们不能通过遍历对象图来到达无法到达的对象。相反,需要进行完全堆扫描,但我认为我们包含了关于元空间中对象的必要信息,扫描后只需从另一个中减去一个