Garbage-First Garbage Collector – G1原理与调优

本文主要介绍G1垃圾收集器的设计思想、实现细节及调优策略(转载请注明出处,若有错误欢迎批评指正)

设计目标

可控延迟下获得尽可能高的吞吐量

应用场景

大内存多处理器的服务端

主要思想

  • 将内存划分为小的Region作为内存回收单位,内存回收时间更短。每个Region均可被指定为新生代或老年代
  • 进行Region的统计信息计算回收收益和成本,优先回收收益较大的Region
  • 分代收集思想,频繁回收新生代,偶尔回收老年代。 普通对象分配在新生代,大对象分配到老年代
  • 回收时使用标记复制算法

工作过程

  • 初始标记:STW短时停顿,标记GCRoots
  • 并发标记:从GCRoot出发进行可达性分析标记,与用户线程并发执行。扫描完成后SATB修正
  • 最终修正:STW短时停顿,完成全部SATB修正
  • 筛选回收:评估回收价值和成本,制定回收计划。STW短时停顿,多线程并行使用标记-复制算法将回收Region的存活对象复制到空Region,然后清空原Region

如何解决并发标记错误

并发错误

DFS标记在与用户线程并发执行时,用户线程会更改对象引用关系,造成 不该删除的节点被误删,以导致严重的并发错误。而该删除的节点没删除则仅仅占用内存,可在后续垃圾回收时再标记删除,称为 浮动垃圾

对象在创建时都是由GCRoots产生并关联的,意味着节点最初都是GCRoots可达的。可达性分析后,所有可达节点都被DFS扫描为黑色,所有不可达节点最终保持白色

DFS已扫描的节点不再扫描,不再扫描的节点新添加对不可达节点的引用,导致不可达节点最终仍未被扫描,并发错误的根源是并发标记结束时出现了黑→白引用,即同时满足 新增黑→白引用删除所有指向该未扫描白色节点引用(不可达的白色节点产生原因) 两个条件

Concurrency Error

SATB

G1采用SATB(Snapshot At The Beginning,原始快照)方式,即暂时保留删除引用的白色节点,打破了第二个条件来解决并发标记错误。G1的SATB实现中,本轮并发标记过程中修改引用的节点记入队列,并在之后作为GCRoot重新扫描。事实上,引用修改同时包括了新增黑→白情况(如下图Round2b)和删除指向白引用(如下图Round1)情况,同时解决了以上两问题。详细分析如下图

SATB

写前屏障和写后屏障

如何解决跨Region引用

1)应将所有持有待删对象引用的对象加入GCRoot,以免造成误删
2)应避免扫描整个引用Region,采用分块思想,记录GCRoot所在Region的内存块索引以计算内存块地址

Card Table

优缺点

  • 内存使用灵活
  • 不会产生内存碎片:标记复制算法避免产生内存碎片
  • 在延迟和吞吐量之间做出平衡:基于Region的策略降低了单次回收停顿时间
  • 占用内存较高:每个Region都有一份卡表保存跨Region引用
  • 执行负载较高:写前屏障记录并发标记过程中的指针变化,写后屏障维护卡表

调优策略

参考资料

周志明. 深入理解Java虚拟机:JVM高级特性与最佳实践[M]. 第3版. 机械工业出版社, 2019.
杨易. 深入解析Java虚拟机HotSpot[M]. 1. 机械工业出版社, 2020.
HotSpot Virtual Machine Garbage Collection Tuning Guide
Getting Started with the G1 Garbage Collector

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

©2018-2024 Howell版权所有 备案号:冀ICP备19000576号