Java G1GC - 卡片表(CT)与 memset (RS)

标签 java garbage-collection jvm g1gc

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

我的理解是:

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

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

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

最佳答案

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

0 1 0 0 0 0

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

      0          1      0     .....

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

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


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

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

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

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

关于Java G1GC - 卡片表(CT)与 memset (RS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65475533/

相关文章:

node.js - 在高负载下,Node.js 的可伸缩性是否会因为垃圾收集而受到影响?

algorithm - 优先分配算法如何减少内存碎片?

Java 11 - 如何覆盖 JVM 和系统内存中的敏感信息(也许使用 System.gc()?)

java - -HeapDumpOnOutOfMemoryError 和 +HeapDumpOnOutOfMemoryError 选项有什么区别?

jvm - BLOCKED 线程会导致高 CPU 消耗吗

java - Tomcat服务器404

java - 寻找简单的 Java 内存缓存

java - android AlarmManager setRepating延时问题

java - 线程中的异常 "main"java.lang.StackOverflowError 递归

java - 这个声明是什么意思?