ZGC 概述
Z Garbage Collector,也称为ZGC,在 jdk 11 中引入的一种可扩展的低延迟垃圾收集器,在 jdk 15 中发布稳定版。在旨在满足以下目标:
- < 1ms 最大暂停时间(jdk < 16 是 10ms,jdk >=16 是 <1ms )
- 暂停时间不会随着堆、live-set 或 root-set 的大小而增加
- 适用内存大小从 8MB 到16TB 的堆
ZGC 具有以下特征:
- 并发
- 基于 region
- 压缩
- NUMA 感知
- 使用彩色指针
- 使用负载屏障
ZGC 的核心是一个并发垃圾收集器,这意味着所有繁重的工作都在Java 线程继续执行的同时完成。这极大地限制了垃圾收集对应用程序响应时间的影响。
ZGC 特征
ZGC 收集器是一款基于 Region 内存布局的,(暂时) 不设分代的,使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记-整理算法的,以低延迟为首要目标的一款垃圾收集器。
内存布局
ZGC 没有分代的概念
ZGC 的内存布局说起。与 Shenandoah 和 G1一样,ZGC 也采用基于 Region 的堆内存布局,但与它们不同的是 , ZGC 的 Region 具 有 动 态 性 (动态创建和销毁 , 以及动态的区域容量大小)。 在 x64硬件平台下 , ZGC 的 Region 可以具有大、中、小三类容量(如下图所示):
- 小型 Region (Small Region ):容量固定为 2M, 存放小于 256K 的对象。
- 中型 Region (Medium Region):容量固定为 32M,放置大于等于256K但小于4M的对象。
- 大型 Region (Large Region): 容量不固定,可以动态变化,但必须为2MB 的整数倍,用于放置 4MB或以上的大对象。
NUMA-aware
NUMA 对应的有 NMA 、UMA 即 Uniform Memory Access Architecture, NUMA 就是 Non Uniform Memory Access Architecture. UMA 表示内存只有一块,所有的 CUU 都要去访问这些内存,那么会存在竞争问题(竞争内存总线访问权),有竞争就要去加锁,有锁效率就会受到影响,而且 CPU 核心数越多,竞争就越激烈。 NUMA 的话每个 CPU 对应有一个内存块,且这块内存在主板上离这个 CPU 是最近的,每个 CPU 优最先访问这块内存,那效率就自然提高了。
服务器的 NUMA 架构在中大型系统上非常流行,也就是高性能的解决方案,尤其在系统延迟方面表现非常优秀,ZGC 是能自动感知 NUMA 架构并且充分利用 NUMA 架构的特征。
染色指针(Colored Pointer)
Colored Pointer, 即染色指针,如图所示, ZGC 的核心设计之一。以前的垃圾收集器的 GC 信息都保存在对象头中,而 ZGC 的 GC 信息保存在指针中(直接把标记信息记录在对象的引用指针上)。
每个对象有一个64位指针,这64位被分为:
- 18位:预留给以后使用;
- 1位: Finalizable标识,此位与并发引用处理有关,它表示这个对象只能通过finalizer才能访问(finalizer:object基类的一个空方法,如果被重写则会在GC之前调用该方法,该方法会且只会被调用一次);
- 1位:Remapped标识,设置此位的值后,对象未指向relocation set中(relocation set表示需要GC的Region集合);
- 1位:Marked1标识;
- 1位: Marked0标识,和上面的Marked1都是标记对象用于辅助GC;
- 42位:对象的地址(所以它可以支持2^42=4T内存):
为什么会有两个 mark 标记?
每一个GC周期开始时,会交换使用的标记位,使上次GC周期中修正的已标记状态失效,所有引用都变成未标记。 GC周期1:使用mark0, 则周期结束所有引用mark标记都会成为 01。 GC周期2:使用mark1, 与周期1相同,所有的mark标记都会成为 10。
ZGC不能做指针压缩?
指针压缩指的是压缩为32位,寻址位数不能超过35,也就是JVM内存最大为32G(2^35=32GB),这里的寻址位数已经达到了42位。
颜色指针的三大优势 ?
- 在一个Region中的所有存活对象都被移走后(复制走后),这个Region就可以被立即释放掉,因为它还有转发表记录着原始地址和新地址,这样的话,理论上,只要还有一个Region对象空闲,ZGC就能完成垃圾收集。
- 颜色指针有指针的“自愈”(Self-Healing)能力,这样子就减少了写屏障(例如三色标记中的增量更新或原始快照),只需要一个读屏障就可以解决问题,减少了内存屏障的使用数量。
- 颜色指针有这极大的扩展性,因为还有18位未使用,这样更有利于后续功能的扩展。