Java G1GC - 卡片表 (CT) 与记忆集 (RS)

问题描述

为什么 g1 需要这两种数据结构?

我的理解是:

  1. CT 保存了老年代引用的实际位置信息。
  2. RS 特定于每个区域,每个区域都有一个与之关联的 RS,它存储有关 指向该区域中对象的外部引用。所以在导航 RS 时,实际位置 可以使用 CT 找到参考。

为什么 RS 不能保存所有信息而不是使用 CT?

是不是因为否则会有太多重复数据存储在不同的 RS 中? 例如 - 年轻代有区域 A 和 B,这两个区域中的对象都有来自老年代的相同外部引用。 在这种情况下,与区域 A 和 B 相关联的 RS 都将存储此冗余信息,这种解释是否正确?

解决方法

让我们先把一些东西按正确的顺序排列。 Card Table 显示该区域可能有传入引用。它确实有点像“哈希”。对于卡片表中的单个字节 - 旧区域中有 许多 个字节。这就像说如果(理论上)你有一张看起来像这样的牌桌(一张牌被标记为“脏”)

0 1 0 0 0 0

对于那个1(脏卡),在扫描年轻区域时,旧区域中的某个映射也需要扫描。

      0          1      0     .....

    0 - 512   512-1024  ...........

因此脏卡对应于老年代的某个部分(从 512 到 1024 字节),也将被扫描,作为年轻代扫描的一部分。


G1 有区域,现在您需要了解 CTRS 如何协同工作。假设 GC 在这个时间点扫描 Region1,它从这个区域取出所有活着的东西并复制到 Region2。同时 Region2 引用了 Region3。如果我们使用 CTRegion2 将被标记为“脏”(通过将特定卡片放入卡片表中)。

下一个周期要扫描 Region3Region3 如何知道是否有other 区域可能指向它?确实有这样的情况:Region2 有对 Region3 的引用。好吧,它可以查看 CT 并检查每个脏卡(以及这些脏卡对应的每个区域),并查看此处是否有来自任何这些区域的引用。想一想:为了清除Region3G1 必须查看整个 CT。在最坏的情况下,它应该扫描整个堆 - 单个区域。

因此:Remembered Sets。这些数据结构是由异步线程根据 CT 所知道的内容填充的。当 Region2 被标记为脏时,异步线程将开始计算其 RS。当需要扫描 Region3 时,它的 RS 将只有一个带有 Region2 的条目。

因此,为了扫描单个区域,G1 需要查看特定的 RS

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...