ZGC
ZGC 收集器是一个可伸缩的、低延迟的垃圾收集器,基于 Region 内存布局的,不设分代,使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记压缩算法
-
在 CMS 和 G1 中都用到了写屏障,而 ZGC 用到了读屏障
-
染色指针:直接将少量额外的信息存储在指针上的技术,从 64 位的指针中拿高 4 位来标识对象此时的状态
-
染色指针可以使某个 Region 的存活对象被移走之后,这个 Region 立即就能够被释放和重用
-
可以直接从指针中看到引用对象的三色标记状态(Marked0、Marked1)、是否进入了重分配集、是否被移动过(Remapped)、是否只能通过 finalize() 方法才能被访问到(Finalizable)
-
可以大幅减少在垃圾收集过程中内存屏障的使用数量,写屏障的目的通常是为了记录对象引用的变动情况,如果将这些信息直接维护在指针中,显然就可以省去一些专门的记录操作
-
可以作为一种可扩展的存储结构用来记录更多与对象标记、重定位过程相关的数据
-
-
内存多重映射:多个虚拟地址指向同一个物理地址
可并发的标记压缩算法:染色指针标识对象是否被标记或移动,读屏障保证在每次应用程序或 GC 程序访问对象时先根据染色指针的标识判断是否被移动,如果被移动就根据转发表访问新的移动对象,并更新引用,不会像 G1 一样必须等待垃圾回收完成才能访问
ZGC 目标:
-
停顿时间不会超过 10ms
-
停顿时间不会随着堆的增大而增大(不管多大的堆都能保持在 10ms 以下)
-
可支持几百 M,甚至几 T 的堆大小(最大支持4T)
ZGC 的工作过程可以分为 4 个阶段:
-
并发标记(Concurrent Mark): 遍历对象图做可达性分析的阶段,也要经过初始标记和最终标记,需要短暂停顿
-
并发预备重分配(Concurrent Prepare for Relocate):根据特定的查询条件统计得出本次收集过程要清理哪些 Region,将这些 Region 组成重分配集(Relocation Set)
-
并发重分配(Concurrent Relocate): 重分配是 ZGC 执行过程中的核心阶段,这个过程要把重分配集中的存活对象复制到新的 Region 上,并为重分配集中的每个 Region 维护一个转发表(Forward Table),记录从旧地址到新地址的转向关系
-
并发重映射(Concurrent Remap):修正整个堆中指向重分配集中旧对象的所有引用,ZGC 的并发映射并不是一个必须要立即完成的任务,ZGC 很巧妙地把并发重映射阶段要做的工作,合并到下一次垃圾收集循环中的并发标记阶段里去完成,因为都是要遍历所有对象,这样合并节省了一次遍历的开销
ZGC 几乎在所有地方并发执行的,除了初始标记的是 STW 的,但这部分的实际时间是非常少的,所以响应速度快,在尽可能对吞吐量影响不大的前提下,实现在任意堆内存大小下都可以把垃圾收集的停顿时间限制在十毫秒以内的低延迟
优点:高吞吐量、低延迟
缺点:浮动垃圾,当 ZGC 准备要对一个很大的堆做一次完整的并发收集,其全过程要持续十分钟以上,由于应用的对象分配速率很高,将创造大量的新对象产生浮动垃圾
参考文章:深入理解JVM(③)ZGC收集器 - 纪莫 - 博客园
总结
Serial GC、Parallel GC、Concurrent Mark Sweep GC 这三个 GC 不同:
-
最小化地使用内存和并行开销,选 Serial GC
-
最大化应用程序的吞吐量,选 Parallel GC
-
最小化 GC 的中断或停顿时间,选 CMS GC