G1的GC模式详解
一、年轻代GC(Young GC)
1. 触发条件
- 阈值动态调整:默认初始阈值 70%(
XX:GCHeapFreeLimit=70),但 G1 会根据历史 GC 效率自动调整,公式:新阈值 = max(30%, min(85%, 历史平均回收效率 * 安全系数))
2.回收流程
2.1 Young GC 的回收范围
graph LR
YoungGC回收 --> 必然回收["所有Eden Region"]
YoungGC回收 --> 必然回收2["所有Survivor Region"]
必然回收 --> 原因1["Eden区对象100%需处理"]
必然回收2 --> 原因2["Survivor区需年龄计算"]
2.2 回收流程
sequenceDiagram
YoungGC->>标记: 标记存活对象
标记->>定位: 确定存活对象位置
定位->>申请: 请求新Region
申请->>分配: 分配Survivor/Old Region
分配->>复制: 复制存活对象
复制->>更新: 更新引用地址
更新->>清空: 原Region加入空闲链表
2.3 空间不足场景
graph TD
空间不足 --> 场景1["无空闲Survivor Region"]
空间不足 --> 场景2["Old区无晋升空间"]
场景1 --> 影响["Survivor溢出"]
场景2 --> 影响["晋升失败"]
2.4 空间不足的处理流
flowchart TD
空间不足 --> 尝试[尝试扩展堆]
尝试 --> 条件{可扩展?}
条件 -->|是| 扩展[扩展堆获取新Region]
条件 -->|否| 触发[触发Full GC]
扩展 --> 成功[分配成功]
触发 --> 回收[Serial Old全堆压缩]
2.5 young gc的简化阶段
sequenceDiagram
YoungGC->>初始标记: 借道STW暂停(<1ms)
初始标记->>复制: 标记直接可达对象
复制->>转移: 复制存活对象到新Region
转移->>清理: 原Region加入空闲链表
与Mixed GC关键差异:
- 无并发标记:Young GC 的标记是 同步完成 的(在STW期间快速扫描)。
- 无最终标记:无需处理SATB队列(因无并发修改)。
- 无Region筛选:强制回收所有年轻代Region。
| 阶段 | Young GC | Mixed GC | 核心差异 |
|---|---|---|---|
| 初始标记 | ✅ 借道STW快速标记GC Roots | ✅ 同Young GC(复用STW窗口) | 实现相同 |
| 并发标记 | ❌ 无 | ✅ 与用户线程并行标记全堆存活对象 | Mixed GC独有,耗时最长 |
| 最终标记 | ❌ 无 | ✅ STW处理SATB队列,修正并发遗漏 | Mixed GC独有,防漏标保障 |
| 筛选回收 | ❌ 无 | ✅ 按价值筛选Old Region并复制 | Mixed GC独有,增量回收核心 |
| 复制存活对象 | ✅ 复制所有年轻代存活对象 | ✅ 复制CSet(Young+筛选的Old) | 目标Region不同 |
2.6 为什么Young GC不需要并发标记?
年轻代特性:
- 对象生命周期短(95%以上在Young GC死亡),无需复杂标记。
- Region数量少(仅占堆20-60%),STW标记开销可控(<5ms)。
二、混合GC(Mixed GC)
1.Mixed GC 的触发条件
1.1 老年代占用阈值
- 当老年代 Region 占用堆内存的比例达到
XX:InitiatingHeapOccupancyPercent(默认 45%)时,触发 全局并发标记周期(Global Concurrent Marking)。 - 此阈值并非立即触发 Mixed GC,而是启动标记为后续回收做准备。
1.2 空间不足兜底
- 若 Young GC 后老年代空间仍不足,或分配大对象(Humongous)失败,也可能提前触发 Mixed GC
2.Mixed GC 的四个核心阶段
2.1 初始标记(Initial Mark, STW)
- 操作:
- 标记所有从 GC Roots 直接可达的对象(如静态变量、线程栈引用等)。
- 借道一次 Young GC 的 STW 时段完成,避免额外停顿。
- 耗时:极短(通常 1-10ms)。
2.2 并发标记(Concurrent Marking)
- 操作:
- 与用户线程并行,递归标记所有存活对象(使用 三色标记法:白→灰→黑)。
- 通过 SATB(Snapshot-At-The-Beginning)和增量更新 机制解决漏标问题:
- 耗时:较长(可能被多次 Young GC 中断)。
2.3 最终标记(Final Remark, STW)
- 操作:
- 处理 SATB 和增量更新,修正并发标记期间的遗漏。
- 扫描 Remembered Set(RSet) 更新跨 Region 引用。
- 耗时:中等(10-50ms,取决于引用变更量)。
2.4 清理与回收(Cleanup & Evacuation)
- 清理(STW):
- 统计各 Region 的存活对象比例,筛选回收价值高的 Old Region(存活率 ≤85%,由
XX:G1MixedGCLiveThresholdPercent控制)。 - 将完全空闲的 Region 直接加入空闲列表。
- 统计各 Region 的存活对象比例,筛选回收价值高的 Old Region(存活率 ≤85%,由
- 回收(Evacuation, STW):
- CSet(回收集合) = 所有 Young Region + 筛选的高价值 Old Region和Humongous Region。
- 使用复制算法将 CSet 中存活对象转移到空闲 Region(Survivor 或 Old)。
- 若空间不足(无足够空闲 Region),触发 Full GC
- 低价值的Old Region不会使用复制算法,但会将死亡的对象空间标记为碎片,加入region内部的碎片链表中管理。
- 低价值的Humongous Region,不会做任何处理,也不回收。因为拷贝大对象太耗性能。
3.Mixed GC 的退化场景(触发 Full GC)
以下情况会导致 Mixed GC 失败并触发 Serial Old GC(Full GC):
3.1 复制阶段空间不足:
- 存活对象复制时无空闲 Region 可用(需调整
XX:G1ReservePercent预留空间)。
3.2 大对象分配失败:
- Humongous Region 无连续空间存放巨型对象。
3.3 并发标记超时:
- 堆满前未完成标记,被迫 Full GC
三、Full GC
Full GC作为垃圾收集器的最后方案,会触发 长时间 STW 停顿(秒级),主要是通过serial收集器作为最后的回收。
1.触发场景
- 并发模式失败(Concurrent Mode Failure)
- 晋升失败(Promotion Failure)
- 大对象分配失败(Humongous Allocation Failure)
- 元空间耗尽(Metaspace Exhaustion)