垃圾回收(三)记忆集&写屏障

297 阅读2分钟

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

记忆集

  1. 用于记录从非收集区域指向收集区域的指针集合抽象数据结构。

  2. 实现:最简单的:非收集区域中所有含跨代引用的对象数组来表示(不考虑效率和成本)。

  3. 缺点:1⃣️空间占用2⃣️维护成本高昂

为了节省记忆集的存储和维护成本,从以下记录精度考虑:

字长精度、对象精度、卡精度

卡精度指的是卡表,卡表是记忆集的具体实现。

HotSpot虚拟机中,卡表的实现就是一个字节数组

每字节数组中的每一个元素都对应着它表示的一块特定大小(2的N次幂)的内存块,被称为卡页。HotSpot中卡页的大小是2的9次幂,即512字节。

一个卡页的内存中可以包含多个对象,只要一个(或多个)对象存在跨代指针,将对应卡表元素的值标识为1,即这个值脏了(Dirty),没有就标识为0。当发生垃圾收集时,筛选变脏的元素,即值为1的元素,加入GC Roots中被扫描。

写屏障

什么是写屏障?

虚拟机在对引用类型对象赋值操作时的AOP切面。

// 即在赋值操作前后程序执行的额外动作
写前屏障
赋值操作A
写后屏障

应用写屏障后,收集器在写屏障加了更新卡表的操作,一旦对象的引用更新,就会产生额外的开销,但是开销跟Minor GC时扫描整个老年代比还是小的。

出了写屏障开销,在高并发场景下,卡表还会出现伪共享。即CPU的缓存系统是以缓存行为单位存储的,当共享同一缓存行的多个对象被多线程修改时,就会互相影响,性能降低。

解决方案:采用条件检查的写屏障,先检查卡表标识,只有卡表元素值不为1的时候,才标记这个元素变脏了。