JVM CardTable 和 RememberedSet

CardTable 和 RememberSet 用于可达性分析

Card Table

官方解释:A kind of remembered set that records where oops have changed in a generation.

将老年代的空间(在 G1 中是每个 Region)分成大小相同的块(一般为 128~512bytes ),叫做卡片(Card),即堆内存最小可用粒度。

Card Table 是一种数组结构存储,每个位置存的是一个 byte,代表一个 Card。一个 byte,有八位,通过约定每一位的含义就可区分不同的使用场景。

Remembered Set

官方解释:A data structure that records pointers between generations.

G1 GC

在 G1 GC 的内存结构中,每个 Region 都会由一个 RSet 维护并跟踪其他 Region 对本 Region 的引用(points-in 结构),也就是存活对象。当 Region 中对象被移动时 RSet 也会更新引用。

当 GC 发生时,通过 RSet 找到引用当前 Region 的 Old Regions 进行扫描,避免了扫描全部的 Old Regions,提高扫描效率。因为每次 GC 都会扫描所有的年轻代的 Regions,所以查找 RSet 时只需要找到 Old Region 对当前 Region 的引用。

RSet 优化

当 Region 被引用较多的情况,RSet 占用空间会上升,因此对 RSet 的记录划分了三种存储粒度:

  • 稀疏表(Sparse):直接通过哈希表来存储,key 是 region index,value 是 card 数组(记录 card index)
  • 细粒度(Fine):当一个 region 的 card 数量超过阈值时,退化为一个 bitmap,每一位对应一个 card(index)
  • 粗粒度(Coarse):当被引用的 region 数量超过阈值时,退化为只记录 regin 引用情况,由 bitmap 存储,每一位对应一个 region(index)
struct g1_rset {
    hash_map<region_id, card_list> sparse;
    hash_map<region_id, bitmap<MAX_CARD>> fine_grained;
    bitmap<MAX_REGION> coarse;
};

CMS GC

Card Table 在 CMS GC 中也有使用到,有一块区域用来记录老年代中的每个 Card 指向新生代的引用(points-out 结构),在进行 YGC 时,这一块区域的对象作为 GC roots,而不需要扫描整个老年代(YGC 时需要知道哪些新生代对象是被老年代引用的)。

并发标记时,如果某个对象的引用发生了变化,标记该对象所在的 Card 为 Dirty Card(通过 write-barrier)。在重新标记时,只需要重新扫描 Dirty Cards 即可,同时清除 Dirty 标记。


http://www.diva-portal.se/smash/get/diva2:754515/FULLTEXT01.pdf
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.63.6386&rep=rep1&type=pdf

Tags:

Add a Comment

电子邮件地址不会被公开。 必填项已用*标注