记忆集与卡表
为了解决对象跨代引用所带来的根节点枚举问题,垃圾收集器在新生代中建立了名为
记忆集(Remembered Set
)的数据结构,用以避免把整个老年代加入GC Roots
扫面范围。
记忆集的实现方案
记忆集是一种抽象的数据结构,用于记录从【非收集区域】指向【收集区域】的指针集合的抽象数据结构。
可以有多种实现,如:
字长精度
每个记录精确到一个机器字长,该字包含跨代指针。
对象精度
每个记录精确到对象,该对象里有字段含跨代指针。
卡精度
每个记录精确到一块内存区域,该内存区域有对象含有跨代指针。
卡表(Card Table)
卡精度就是用一种称为卡表(Card Table
)的方式去实现记忆集,这是目前最常见的一种记忆集实现方式。
卡表最简单的形式只是一个字节数组,HotSpot
虚拟机默认的卡表标记逻辑:
CARD_TABLE [this address >> 9] = 0;
字节数组CARD_TABLE
的每一个元素都对应着标识的内存区域中一块特定大小的内存空间,
这个内存空间被称为“卡页”(Card Page
)。一般卡页大小都是2的N
次幂的字节数。
HotSpot
中使用的是卡页是2的9次幂,即512字节(地址右移9位,上边的卡表标记代码也可看出)。
一个卡页的内存中通常包含不止一个对象,只要卡页内有一个对象存在跨代指针,
那么对应的卡表的数组元素的值标识为1,称这个元素变脏(Dirty
),没有则标识为0。
垃圾回收时,只需要筛选出卡表中变脏的元素,就能得到哪些卡页内存块中包含跨代指针,从而将
它们加入GC Roots
中一并扫描。