G1 垃圾回收的阶段

295 阅读4分钟

G1 垃圾回收的阶段

本文禁止转载。

鉴于网络上关于 G1 垃圾回收器的回收过程描述不一,经常出现对于回收过程的过度简化,本文旨在明确说明 G1 垃圾回收器的回收过程,主要依据是官方文档,开发人员博客等内容。相信通过对回收过程的了解,可以高效地进行调优,而不只是应对面试。

注:本文不会对于某些概念进行解释,对于具体实现细节也不会过多涉及。你应该先了解 记忆集 Remembered Set、Collection Set(CSset)、SATB 算法、三色标记法、写屏障、region 划分等概念或实现。

G1 中的 GC

Young GC 和 Old GC, 其中 Old GC 又叫做 Mixed GC,同时回收新生代和老年代。G1 中不提供 Full GC 的实现,由其他垃圾回收器实现,不当的配置会导致 Full GC 的出现。Young GC 使用标记复制算法,Mixed GC 使用标记整理算法。

GC 的时机

随着程序启动,Young GC 的进行过程中,会不断将一部分对象复制到 S 区和 O 区,老年代对象逐步增多,整体内存占用逐步增多。YOUNG GC 和 Mixed GC 各自有不同的阶段,当内存占用达到 45%时(-XX: InitiatingHeapOccupancyPercent 可配置),开始全局并发标记(global concurrent marking),之后会进行 Mixed GC。

简单来说,G1GC 分成标记、回收两个阶段。Young GC 相比于 old GC 的频率很高。

以下为 Oracle 关于回收阶段的示意图:

image.png

从图中可以看出:并发标记开始到 MixedGC 开始,经过了多次 Young GC。根据回收区域的不同,G1 分成了只回收新生代和混合回收两个阶段,两个阶段交替循环。

Young GC 阶段

  1. Root Scanning 根扫描
  2. Update RSet 更新记忆集
  3. Process Rest 处理记忆集
  4. Object Copy 对象拷贝
  5. Reference Processing 处理引用

根扫描中的根包括栈上引用、静态引用。

更新记忆集:处理脏表,更新 RSet

处理记忆集:找到老年代对于新生代的引用。

对象拷贝包括 1. 遍历引用 2. 拷贝存活对象到 S 区或 O 区

处理引用指的是处理软、弱、虚、终结器引用。

并发标记循环(Concurrent Marking Cycle)

内存占用达到阈值时,触发并发标记循环,标记成功后会进行 Mixed GC

  1. Initial mark phase 初始标记(STW)
  2. Root region scanning phase 根区域扫描
  3. Concurrent marking phase 并发标记
  4. Remark phase 重新标记(STW)
  5. Cleanup phase 清理(STW)

初始标记:基于 Young GC, 使用 Young GC 的标记结果。

根区域扫描:基于上一步得到的新生代标记对象,标记指向老年代的引用。早于下一次 Young GC 的执行。

并发标记:并发标记所有可达对象,也就是存活对象。

重新标记:完成标记,处理完成 SATB 队列,处理引用(非强引用)。

清理:确定需要清理的 region,区分完全是垃圾的 region, 没有垃圾的 region(可以设定阈值-XX: G1HeapWastePercent = 5,如不超过 5%,无需清理),垃圾与存活对象共存的区域。对于完全是垃圾的区域可以并发清理。使用标记信息重建 RSet。

Mixed GC

当并发标记成功后,回收新生代和部分老年代(默认 1/8,-XX: G1MixedGCCountTarget = 8)。多次 Mixed GC 后,回收完标记的老年代垃圾,开始只进行 Young GC 的阶段。

更详细的并发标记过程

Concurrent Mark Cycle States

以上图片摘自 G1 开发负责人的博客,分析一下图中的具体实现和之前提到并发标记循环的差别:

Concurrent Clear Claimed Marks 开始了对类对象和类加载器的卸载过程。并发标记过程分成了三个部分,其中 preclean 阶段对于非强引用进行预处理。再标记过程可能重新进入并发标记,如图中虚线所示。

总结

  1. Young GC 和 Mixed GC 均考虑了跨代引用问题,一个使用的是 RSet, 一个使用的是 Young GC 标记的结果。
  2. 通过了解垃圾回收的不同阶段,可以理解相关参数调优,保证垃圾回收的速度大于产生的速度,避免 Full GC。
  3. G1 在不断优化中,其实现随着 JDK 版本不同也有所差异,回收阶段有细微差异。

参考资料

  1. www.oracle.com/technetwork…
  2. docs.oracle.com/en/java/jav…
  3. tschatzl.github.io/2022/08/04/…
  4. www.youtube.com/watch?v = Gee7QfoY8ys