深入理解Java虚拟机——记忆集与卡表

409 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

记忆集

记忆集用于解决对象跨代引用带来的问题,在新生代建立记忆集避免将整个老年代加进GC Roots扫描范围,实际上,所有涉及部分区域收集行为的垃圾收集器都面临相同的问题。记忆集最简单的实现可以用数组来实现,在垃圾收集的场景中由于只需要判断一块非收集区域是否存在指向收集区域的指针就可以,因此可以选择更为粗犷的记忆粒度,包含:字长精度(精确到机器字长,即处理器的寻址位数,该字含有跨代指针)、对象精度(精确到每个对象,对象中的字段含有跨代指针)和卡精度(精确到一块内存区域,该块内存含有跨代指针)。

其中卡精度指卡表,这是最常用的记忆集实现方式,

卡表

卡表是粒度为内存区域的记忆集,用于记录哪些内存区域上存在跨代引用,可以将其看做一个字节数组,每个元素对应着一块特定大小的内存块,被称为卡页。

CARD_TABLE[this address >> 9] = 0;

上面代码表示卡页的大小是2的9次幂,如果卡表标识的内存区域起始地址是0x0000,那么0、1、2号元素就分别对应了0x00000x01FF、0x02000x03FF、0x0400~0x05FF的卡页内存块。

一个卡页中包含多个对象,只要有一个对象的字段存在跨代指针,那么卡表中的元素值就为1(称为脏元素),否则为0。在垃圾收集时,只要扫描脏元素即可得出哪些内存中有跨代引用。