记忆集和卡表
为了解决对象跨代引用所带来的问题,垃圾收集器在新生代中建立了名为记忆集(Remembered Set)的数据结构,用以避免把整个老年代加进GC Roots扫描范围。事实上并不是只是新生代、老年代之间才有跨代引用的问题,所有涉及部分区域收集行为的垃圾收集器,典型如G1,ZGC收集器,都会面临相同的问题,因此我们有必要进一步理清记忆集的原理和实现方式。
**记忆集是一种用于记录从非收集区域指向收集区域的指针集合的抽象数据结构。**下面列举了一些可供选择的记录精度,由高到低依次为:
- 字长精度:每个记录精确到一个机器字长(就是处理器的寻址位数,如常见的32位或64位,这个精度决定了机器访问物理内存地址的指针长度),该字包含跨代指针。
- 对象精度:每个记录精确到一个对象,该对象里有字段含有跨代指针。
- 卡精度:每个记录精确到一块内存区域,该区域内有对象含有跨代指针。
卡精度所指的是用一种称为"卡表"(caed table)的方式实现记忆集,是目前最常用的一种实现方式,卡表与记忆集的关系,类似于Java语言中HashMap与Map的关系。
卡表技术是指:将整个堆划分为一个个指定大小的内存块,这个内存块称为"卡页",卡页大小在HotSpot中默认为512字节,并且维护一个卡表(可以是一个字节数组)。一个卡页的内存中通常包含不止一个对象,只要卡页内有一个(或多个)对象的字段存在着跨代指针,那就将对应卡表的数组元素的值标识为1,称为这个元素变脏(Dirty),没有则标识为0。
有了卡表之后,我们看看其在实际应用中是怎么工作的。比如在进行Minor GC的时候,我们便不用扫描整