NingG +

JVM 实践:G1 垃圾收集器

0.概要

写在开头:当前文章,都是针对 JDK8 中 G1 的实现,进行描述的

G1 垃圾收集器的详解,几个方面:

  1. 工作原理:
    1. 内存特点
    2. GC:
      1. young gc
      2. mixed gc
      3. full gc
  2. 实践:
    1. 常用参数
    2. 常见问题

1.内存特点:G1

内存特点

关联术语

关键用途

2.GC:G1

G1 垃圾收集器,具体的 GC,分为下述几种:

  1. young gc:标记-复制
    1. 「新生代」的垃圾回收
    2. CSet 中,只包含 Eden、Survivor
  2. mixed gc:标记-复制
    1. 「新生代」和「部分老年代」的垃圾回收
    2. CSet 中,包含 Eden、Survivor、部分 Old、Humongous
  3. full gc
    1. G1 gc 失败,退化为 Serial 方式
    2. 单线程全堆扫描,对整个 Heap 进行垃圾回收,涵盖所有的「新生代」和「老年代」

特别说明

G1 垃圾收集器,GC 都是针对 CSet 进行的

2.1.Young GC

Young GC,关键细节:

Young GC 的执行过程:就是「标记-复制」算法

  1. 根扫描
  2. 确定「老年代」对「新生代」的引用,避免全堆扫描:
    1. 根据 card table,扫描 dirty 部分,更新 RSet
    2. 新生代中,根据 RSet,确定 Old 对 Eden 和 Survivor 对象的引用
  3. 标记复制:将存活对象,放入到 Survivor 区 或者 Old 区
    1. 新的 Survivor 区:是 Free Region 升级来的
    2. 被释放的 Eden 和 Survivor 区:会标记为 Free Region 空白的可用分区

Tips:

2.2.Mixed GC

Mixed GC,关键细节:

Mixed GC 的执行过程:就是「标记-复制」算法

  1. 并发标记周期:针对 Old 分区,进行标记
    1. 初始标记:依赖 Young GC
    2. 扫描根分区:如果有 Young GC,则,Young GC block 阻塞等待
    3. 并发标记
      1. 可以并发进行 Young GC
      2. 结束后,并不会进入 Young GC 阶段
    4. 重新标记:不能进行 Young GC
    5. 筛选回收:结束后,进入 mixed 阶段
  2. Mixed GC本质就是对 CSet 中 Region 的回收
    1. CSet:在 mixed 模式下,其中涵盖了 Eden、Survivor、Old、Humongous Region
    2. 筛选回收阶段:针对 Old 分区
      1. 完全可回收的 Region:不存在存活的对象,直接回收 Region,标记为 Free Region 可用分区
      2. 存在部分存活的对象的 Region:标记分数后,追加在 C-Set 中

实际上,可以认为是 2 条线:

1 个插图:并发标记周期的说明

特别说明

G1的收集都是STW的;

但「年轻代」和「老年代」的 GC 界限模糊,采用了混合(mixed)收集的方式。

Young GC,可能快速切换为 Mixed GC,只要 X 标记的 Old Region 存在和消失,就会自动升级 or 降级;

这样,即使堆内存很大时,也可以限制收集 Region 的范围,从而降低停顿,达到设置的「暂停时间的目标」。

2.3.其他

2.3.1.启发式算法

启发式算法:根据执行状态,动态调整

  1. 设置了「暂停时间的目标」(默认 200ms),G1 会自动调整「年轻代」的空间大小
  2. 如果显式设置「年轻代」的大小,则,用户设置的「暂停时间的目标」会自动失效

2.3.2.SATB,增量式的标记算法

G1 垃圾收集器,采用了 SATB(Snapshot At The Beginning),初始快照,增量式的标记算法,具体:

  1. 标记开始时:Region 创建一个 Snapshot
  2. 存量标记:只针对 Snapshot 中存活的对象,进行标记
  3. 增量标记:Snapshot 之后,新生成的对象,都被标记为「存活对象」,此次不回收,下次标记再说

2.3.3.G1:适用场景

就目前而言、CMS还是默认首选的GC策略、可能在以下场景下G1更适合:

  1. 多核+大内存:服务端多核CPU、JVM内存占用较大的应用(至少大于4G)
  2. 业务多碎片:应用在运行过程中会产生大量内存碎片、需要经常压缩空间
  3. 防止高并发雪崩:想要更可控、可预期的GC停顿周期;防止高并发下应用雪崩现象

2.4.小结

G1 垃圾收集器,围绕其 Young GC 和 Mixed GC,从整体宏观的角度上,跟之前所有的「串行」「并行」「并发」的垃圾收集器,存在本质的差异:

  1. 之前的垃圾收集器,要实现 2 个基本步骤
    1. 步骤1:找到需要回收的对象
    2. 步骤2:回收
    3. Note:上面两个步骤「步骤2」依赖「步骤1」,并且串行进行
  2. G1 垃圾收集器,在「老年代」,把 2 个步骤「同时进行」:
    1. 找到需要回收的对象
      1. 在找到需要回收的 Old Region 过程中,仍然可以同时「回收对象」,即 GC
      2. 找到需要回收的 Old Region 过程,称为「并发标记周期
    2. 回收对象
      1. 在「找需要回收的对象」过程中,可以持续并发的进行 GC,称为 Young GC,只会收「新生代」
      2. 「找需要回收的对象」过程结束后,再进行的 GC,称为 Mixed GC,会同时回收「新生代」和「部分老年代」

参考示意图:

3.实践

2 个方面:

  1. 常用参数
  2. 常见问题

TODO:

4.参考资料

同类文章:

微信搜索: 公众号 ningg ,即可联系我

Top