java - 如果我们在年轻代上标记了所有死亡对象后就知道了它们,为什么我们需要在老一代中专门搜索无法访问的对象呢?

标签 java garbage-collection jvm g1gc

我知道在 CMS 和 G1 中堆被分为 Eden、Survivor 空间和 Old Generation,唯一的区别是在 CMS 中这种划分是真实的(这些空间是连续的并且位于内存的不同部分)而在 G1 中它是逻辑的(堆被分成 ±2000 个动态区域,每个区域从 1 到 32 MB)。

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

如果堆的填充达到阈值,则在 G1 中开始混合疏散(Young + Old)。 在老一代中创建死亡对象是基于“Remembered Sets”。每个区域都有一个 memset ,列出了从外部指向该区域的引用。这些引用被视为额外的 GC 根。

G1 决定将老一代和年轻代的哪些区域添加到集合集中。

如果我们拥有所有对象的完整图并且在将它们标记在年轻代疏散级别上之后知道所有活着和死亡的对象,为什么我们需要 memset 和对老年代中无法访问的对象进行特定搜索?

最佳答案

Remembered Set(或CMS中的Card Table)背后的想法不是“搜索Old Generation中无法访问的对象”,而是为了在Young收集期间移动 Activity 对象时快速识别Old Generation中需要更新的引用.

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

关于java - 如果我们在年轻代上标记了所有死亡对象后就知道了它们,为什么我们需要在老一代中专门搜索无法访问的对象呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47543540/

相关文章:

java - 非常快地跳到双向链表的中间

java - 您能解释一下这个 GC 日志消息吗?

java - asm 编译器中的二进制表达式

java - Spring 中的服务外观

java - 为枚举实现 MessageBodyReader

java - 使用线程在java中发送批量电子邮件?

java - GC在这里收集什么?

go - 如何将Go的GC CPU使用率提高到25%以上?

garbage-collection - System.gc() 会触发什么样的 GC?

java - 在 Java 中,新建或增强类加载器的用例是什么?