G1 GC(Garbage-First Garbage Collector)原理详解

        G1 GC(Garbage-First)是 Java HotSpot 虚拟机中的一款面向服务端、低延迟、高吞吐的垃圾回收器,自 JDK 7u4 引入,并在 JDK 9 成为默认垃圾回收器。G1 的设计目标是在可控的停顿时间内(Soft Real-Time)实现高吞吐量,适用于大内存(数十GB甚至更大)的应用场景。

1. G1 GC 的核心设计思想

G1 的核心思想是:

  1. 分块(Region-Based)

    • 将堆划分为多个大小相等的 Region(默认约 2048 个,每个 Region 大小 1MB~32MB)。

    • 每个 Region 可以是 Eden、Survivor、Old、Humongous(大对象) 中的一种。

    • 动态调整 Region 的角色,避免传统分代 GC 的固定比例限制。

  2. 增量回收(Incremental Collection)

    • 每次只回收部分 Region(而非整个堆),减少单次 GC 停顿时间。

    • 通过 Remembered Sets(RSet) 和 Card Table 记录跨 Region 引用,避免全堆扫描。

  3. 可预测停顿模型(Soft Real-Time)

    • 通过 -XX:MaxGCPauseMillis(默认 200ms)设定目标停顿时间。

    • G1 会动态调整回收的 Region 数量,尽量满足停顿时间要求。


2. G1 GC 的内存布局

G1 的堆不再严格分为新生代和老年代,而是由多个 Region 组成:

Region 类型说明
Eden存放新分配的对象
Survivor存放 Minor GC 后存活的对象
Old存放长期存活的对象
Humongous存放超大对象(>50% Region 大小)
Free空闲 Region,可用于分配新对象

特点

  • 动态调整:新生代和老代的大小不固定,由 G1 自动调整。

  • 大对象优化:Humongous 对象直接进入老年代,避免多次拷贝。


3. G1 GC 的工作流程

G1 的垃圾回收分为 Young GC 和 Mixed GC 两种模式:

(1) Young GC(Minor GC)

触发条件:Eden 区满时触发。
过程

  1. 根扫描(Root Scanning):多线程并行扫描 GC Roots(栈、静态变量等)。

  2. 标记存活对象:标记 Eden 和 Survivor 区的存活对象。

  3. 复制存活对象

    • 存活对象被复制到新的 Survivor 区(或晋升到 Old 区)。

    • 清空 Eden 和旧的 Survivor 区。

  4. 更新 RSet:记录跨 Region 引用。

特点

  • 并行执行,减少 STW 时间。

  • 动态调整新生代大小,适应不同负载。


(2) Mixed GC(Major GC)

触发条件:当老年代占用达到 -XX:InitiatingHeapOccupancyPercent(默认 45%)时触发。
过程

  1. 初始标记(Initial Mark,STW):标记 GC Roots 直接关联的对象(与 Young GC 同步执行)。

  2. 并发标记(Concurrent Mark):多线程并发标记所有存活对象。

  3. 最终标记(Remark,STW):修正并发标记期间变动的引用(使用 SATB 算法)。

  4. 清理阶段(Cleanup,STW)

    • 统计各 Region 的存活对象比例,排序回收价值(Garbage-First)。

    • 选择部分 Old Region 进行回收(Mixed GC)。

  5. 复制/整理(Evacuation):将存活对象复制到空闲 Region,并清理死亡对象。

特点

  • 增量回收:每次 Mixed GC 只回收部分 Old Region,避免长时间停顿。

  • 可预测停顿:通过选择回收价值高的 Region(垃圾比例高),最大化回收效率。


4. G1 GC 的关键技术

(1) Remembered Set(RSet)

  • 每个 Region 维护一个 RSet,记录其他 Region 对本 Region 的引用

  • 避免全堆扫描,提高回收效率。

(2) Card Table

  • 将堆划分为 512B 的 Card,记录脏 Card(被修改的引用)。

  • 用于辅助 RSet 更新。

(3) SATB(Snapshot-At-The-Beginning)

  • 在并发标记阶段,G1 使用 SATB 算法记录标记开始时的对象图快照。

  • 确保并发修改不会影响标记准确性。


5. G1 GC 核心参数

参数作用默认值
-XX:+UseG1GC启用 G1 GCfalse(JDK9+ 默认 true
-XX:MaxGCPauseMillis目标最大停顿时间200(ms)
-XX:InitiatingHeapOccupancyPercent(IHOP)触发 Mixed GC 的老年代占用阈值45(%)
-XX:G1HeapRegionSize设置 Region 大小自动计算(1MB~32MB)
-XX:ParallelGCThreads并行 GC 线程数CPU 核心数
-XX:ConcGCThreads并发标记线程数ParallelGCThreads / 4

6. G1 GC 的优缺点

✅ 优点

  1. 可控停顿时间:适合低延迟应用(如金融交易、实时系统)。

  2. 大堆友好:适合数十 GB 甚至更大的堆内存。

  3. 内存整理:通过复制算法减少碎片。

  4. 自适应调整:动态调整新生代/老年代比例。

❌ 缺点

  1. 内存占用较高:RSet 和 Card Table 需要额外空间。

  2. 并发阶段 CPU 开销:并发标记会占用应用线程资源。

  3. Full GC 仍可能发生(如晋升失败或并发模式失败时)。


7. G1 GC 适用场景

  • 堆内存较大(6GB+) 的应用。

  • 要求低延迟(<200ms) 的服务(如 Web 服务、微服务)。

  • 替代 CMS,避免内存碎片问题。


8. G1 vs Parallel GC vs CMS

回收器算法停顿时间适用场景
Parallel GC分代+并行 STW高吞吐,长停顿计算密集型
CMS并发标记-清除低停顿,高碎片中小堆,低延迟
G1分区+标记整理可控停顿,低碎片大堆,平衡吞吐/延迟
ZGC全并发+染色指针超低停顿(<10ms)超大堆,极致低延迟

总结

  • G1 GC 采用 Region 分区模型,支持增量回收和可预测停顿

  • 通过 Young GC + Mixed GC 组合,平衡吞吐和延迟

  • 适合大内存、低延迟场景,是 CMS 的替代方案

  • 在 JDK 9+ 中已成为默认 GC,适用于现代 Java 应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值