一文了解ZGC垃圾收集器

203 阅读3分钟

G1的问题

标记复制算法分为

  1. 标记阶段,即从GC Roots集合开始,标记活跃对象;

  2. 转移阶段,即把活跃对象复制到新的内存地址上;

  3. 重定位阶段,因为转移导致对象的地址发生了变化,在重定位阶段,所有指向对象旧地址的指针都要调整到对象新的地址上。

**G1的混合回收过程可以分为标记阶段、清理阶段和复制阶段 **

四个STW过程中,初始标记因为只标记GC Roots,耗时较短。再标记因为对象数少,耗时也较短。清理阶段因为内存分区数量少,耗时也较短。复制阶段要处理所有存活的对象,耗时会较长。因此,G1停顿时间的瓶颈主要是标记-复制中的转移阶段STW。为什么转移阶段不能和标记阶段一样并发执行呢?主要是G1未能解决转移过程中准确定位对象地址的问题。

image.png

ZGC对标记复制算法做了重大改进:

ZGC在标记、转移和重定位阶段几乎都是并发的

ZGC只有三个STW阶段:初始标记,再标记,初始转移。其中,初始标记和初始转移分别都只需要扫描所有GC Roots,其处理时间和GC Roots的数量成正比,一般情况耗时非常短;再标记阶段STW时间很短,最多1ms,超过1ms则再次进入并发标记阶段。即,ZGC几乎所有暂停都只依赖于GC Roots集合大小,停顿时间不会随着堆的大小或者活跃对象的大小而增加。与ZGC对比,G1的转移阶段完全STW的,且停顿时间随存活对象的大小增加而增加。

ZGC通过着色指针和读屏障技术,解决了转移过程中准确访问对象的问题,实现了并发转移。

在ZGC中,应用线程访问对象将触发“读屏障”,如果发现对象被移动了,那么“读屏障”会把读出来的指针更新到对象的新地址上,这样应用线程始终访问的都是对象的新地址

着色指针

着色指针是一种将信息存储在指针中的技术。

一个对象有三个虚拟地址,且都对应同一个物理地址,但这三个空间在同一时间有且只有一个空间有效。

读屏障

读屏障是JVM向应用代码插入一小段代码的技术。当应用线程从堆中读取对象引用时,就会执行这段代码。需要注意的是,仅“从堆中读取对象引用”才会触发这段代码。

在对象标记和转移过程中,用于确定对象的引用地址是否满足条件,并作出相应动作。

详细过程

起初对象的虚拟地址都为Remapped视图

在并发标记后,如果对象被标记那么虚拟地址修改为M0视图,代表对象活跃;对象的地址是Remapped视图,说明对象是不活跃的。

并发转移阶段,将为M0视图的对象转移走,然后恢复为Remapped视图。原位置的Region仍持有原始地址,可以用于并发操作

第二次并发标记阶段后:地址视图调整为M1,而非M0。

参考:新一代垃圾回收器ZGC的探索与实践 - 掘金 (juejin.cn)