TL;DR(30 秒扫完)
- 演进:Serial → Parallel → CMS → G1 → ZGC/Shenandoah
- 权衡三角:吞吐 vs 停顿 vs 空间,不可兼得
- 三层漏斗:JDK 版本(硬约束)→ 内存规模(G1 4-32GB 最佳)→ 业务特征(吞吐/延迟/空间优先)
- G1 核心优势:Region 结构 + 可预测停顿 + Mixed GC 避免退化 Full GC
- ZGC 核心:读屏障+多映射,STW <1ms,堆 8MB-16TB
关键结论
结论 AGC 器没有最好的,只有最适合的——按 JDK 版本定范围,按内存规模定候选,按业务特征定取舍
结论 BG1 是 JDK 9+ 默认,4-32GB 堆最佳,Web 服务通用推荐
结论 CZGC JDK 15 GA,堆 4GB+,STW <10ms,JDK 21 引入分代 ZGC
结论 D核心调优参数
-Xms=-Xmx 避免动态扩缩结论 E评估靠 GC 日志+JFR,关注 GC 频率、STW P99、FullGC 次数、堆使用率
完整讲解(费曼四步)
STEP 1 · 概念
GC 器选型本质是在吞吐 vs 停顿 vs 空间的权衡三角里做取舍。JDK 版本决定可用 GC 器范围,内存规模决定候选,业务特征决定取舍。STEP 2 · 大白话
类比:GC 器选型像买车。
- JDK 版本:决定你有哪些车型可选(老车买不到新车款)
- 内存规模:堆 1GB 用 Serial(小车),16GB 用 G1(家用车),64GB+ 用 ZGC(大车)
- 业务特征:批量运输用 ParallelGC(载重),市内通勤用 G1(舒适),长途高速用 ZGC(低延迟)
没有最好的车,只有最适合你行程的车。
STEP 3 · 底层
GC 器演进主线
| GC 器 | 引入版本 | 特点 | 现状 |
|---|---|---|---|
| Serial | JDK 1.2 | 单线程,为快而生 | 小堆单核(<1GB) |
| ParallelGC | JDK 5 | 并行化,求吞吐 | JDK 8 默认 |
| CMS | JDK 5 | 并发标记-清除,求停顿 | JDK 14 弃用移除 |
| G1 | JDK 7 | Region+可预测停顿 | JDK 9+ 默认 |
| ZGC | JDK 15 GA | 读屏障+多映射,STW <1ms | TB 级堆首选 |
| Shenandoah | JDK 11 | 写屏障+Brooks 转发,STW <10ms | RedHat 主推 |
三层漏斗决策
第一层:JDK 版本(硬约束)- JDK 8 用不了 ZGC(ZGC JDK 15 GA)
- JDK 14 之后 CMS 被移除
- JDK 9+ 默认 G1
- JDK 21 引入分代 ZGC
- Serial:<1GB
- G1:4-32GB 最佳
- ZGC:4GB+,可到 16TB
- Shenandoah:32GB+
- 批处理/后台任务 → ParallelGC(吞吐优先)
- Web 服务通用 → G1(推荐)
- 低延迟+大堆 → ZGC
- 需要并发优先 → Shenandoah
GC 器对比表
| GC 器 | 吞吐 | 停顿 | 空间 | 堆规模 | 推荐场景 |
|---|---|---|---|---|---|
| Serial | 低 | 长 | 高 | <1GB | 嵌入式、单核 |
| ParallelGC | 高 | 中 | 中 | 4-32GB | 批处理、后台任务 |
| CMS | 中 | 短(但有碎片) | 中 | 已弃用 | JDK 14 移除 |
| G1 | 中 | 可预测 | 中 | 4-32GB | Web 服务通用 |
| ZGC | 中 | 极短 <10ms | 中 | 4GB-16TB | 大堆、低延迟 |
| Shenandoah | 中 | 短 <10ms | 中 | 32GB+ | 并发优先 |
G1 的核心优势
- Region 结构:堆切成等大 Region(1MB-32MB),回收选最脏的 Region 优先,避免整堆扫描
- 可预测停顿:
-XX:MaxGCPauseMillis目标停顿,G1 自动决定每次回收多少 Region - Mixed GC:Young + 部分老年代 Region,避免退化到 Full GC
- 无碎片:Region 内可整理
ZGC 的核心优势
- 读屏障+多映射:STW 只有 Initial Mark 和 Final Relocate 两瞬间,都 <1ms
- 堆 8MB-16TB:大堆首选
- 堆外内存感知:JDK 21+ 可管理 DirectByteBuffer 生命周期
- JDK 21 引入分代 ZGC(Young/Old 分区)
实战调优参数
G1 关键参数:-XX:+UseG1GC # 启用 G1
-XX:MaxGCPauseMillis=200 # 目标停顿(默认 200ms)
-XX:G1HeapRegionSize=16m # Region 大小(默认动态)
-XX:InitiatingHeapOccupancyPercent=45 # 并发标记启动阈值(默认 45%)
-Xms4g -Xmx4g # 堆大小(建议相等)
ZGC 关键参数:
-XX:+UseZGC # 启用 ZGC
-Xms4g -Xmx4g # 堆大小(建议相等)
通用必备:
-Xms=Xmx # 避免动态扩缩开销
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=512m
-XX:MaxDirectMemorySize=512m # 堆外内存上限
-XX:+HeapDumpOnOutOfMemoryError # 救命参数
-Xlog:gc* # GC 日志(JDK 9+)
GC 评估手段
GC 日志:- JDK 9+:
-Xlog:gc* - JDK 8:
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps
jdk.GCPhasePause:GC 各阶段耗时jdk.GCHeapSummary:堆使用汇总jdk.GCObjectAllocationInNewTLAB:TLAB 分配jdk.Safepoint:安全点事件
- Prometheus + JVMExporter
- Grafana 大盘
- GC 频率(每秒数次 YoungGC 正常,FullGC 应极少)
- STW P99(生产要求 <200ms)
- FullGC 次数
- 堆使用率(FullGC 后仍 >70% 说明有泄漏)
- Metaspace 使用率
场景选型参考
| 场景 | 堆大小 | JDK 版本 | 推荐 GC |
|---|---|---|---|
| 嵌入式/单核 | <1GB | 任意 | Serial |
| 批处理/后台 | 4-32GB | JDK 8+ | ParallelGC |
| Web 服务通用 | 4-32GB | JDK 8+ | G1(推荐) |
| Web 服务低延迟 | 4-32GB | JDK 15+ | ZGC |
| 大堆服务 | 32GB-16TB | JDK 15+ | ZGC |
| 需要并发优先 | 32GB+ | JDK 11+ | Shenandoah |
JDK 8 → JDK 17 升级注意点
- CMS 已弃用(JDK 14 移除),必须换 G1/ZGC
- 模块系统(JPMS)
- Finalization 弃用改 Cleaner
-Xlog替代-XX:+Print*- JFR 事件更丰富
STEP 4 · 简化
一句话总结:GC 器没有最好的,只有最适合的——三层漏斗决策,G1 是通用答案,ZGC 是大堆进阶。记忆口诀:
- 三层漏斗:JDK → 内存规模 → 业务特征
- G1 三优势:Region / 可预测 / Mixed
- ZGC 二件套:读屏障 + 多映射
- 评估三指标:GC 频率 / STW P99 / FullGC 次数
常见误区
"CMS 还是可用的"
JDK 14 已移除,JDK 17/21 用不了
"G1 可以支持任意堆大小"
G1 在 4-32GB 最佳,超过 32GB 停顿开始退化
"ZGC 需要大堆才用"
ZGC 从 4GB 起也能跑,JDK 21 分代 ZGC 更优
"
-Xms 和 -Xmx 分开设没问题"建议相等避免动态扩缩开销
"G1 停顿时间固定"
G1 是可预测停顿(
-XX:MaxGCPauseMillis 是目标),实际由 Region 大小决定延伸追问
G1 的 Region 和传统分代区别?
G1 是逻辑分代(Region 标记为 Young/Old/Humongous),不是物理分代;回收选任意 Region,避免整堆扫描
ZGC 如何实现 <10ms 停顿?
并发标记+并发整理+读屏障+多映射;移动对象时改映射而非改引用;STW 只有 Initial Mark 和 Final Relocate 两瞬间
如何在生产上评估 GC 是否合适?
GC 日志
-Xlog:gc*、JFR jdk.GCPhasePause、Prometheus + JVMExporter;关键指标:GC 频率、STW P99、FullGC 次数、堆使用率JDK 8 升级到 JDK 17 要注意什么?
CMS 已弃用(JDK 14 移除)必须换 G1/ZGC;模块系统(JPMS);Finalization 弃用改 Cleaner;
-Xlog 替代 -XX:+Print*;JFR 事件更多什么时候从 G1 换 ZGC?
堆 >32GB、P99 STW 敏感(如支付/实时交易)、JDK 15+、可接受略低吞吐;换 ZGC 前要压测对比吞吐和延迟
速查表
GC 演进: Serial → Parallel → CMS(弃用) → G1 → ZGC/Shenandoah
三层漏斗:
1. JDK 版本 (硬约束)
2. 内存规模 (4-32GB 用 G1, >32GB 用 ZGC)
3. 业务特征 (吞吐/延迟/空间)
场景选型:
<1GB → Serial
4-32GB Web → G1
>32GB 低延迟 → ZGC
批处理 → ParallelGC
关键参数:
G1: -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45
ZGC: -XX:+UseZGC
通用: -Xms=Xmx (避免扩缩)
评估指标:
GC 频率 / STW P99 / FullGC 次数 / 堆使用率
Anki 候选卡片
Q: GC 器演进主线?
A: Serial → Parallel → CMS(弃用)→ G1 → ZGC/Shenandoah
Q: G1 三大优势?
A: Region 结构 / 可预测停顿 / Mixed GC
Q: ZGC 核心技术?
A: 读屏障 + 多映射,STW <1ms
Q: G1 关键调优参数?
A:
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45Q: JDK 8 升级到 JDK 17 最需注意?
A: CMS 已弃用(JDK 14 移除),必须换 G1/ZGC
关联题目
关联知识
GC 器没有最好的只有最适合的——按 JDK 版本定范围,按内存规模定候选,按业务特征定取舍
GC 器选型像买车:JDK 版本=车型可选;内存规模=小车/家用车/大车;业务=载重/舒适/低延迟
✦ 记 忆 口 诀 ✦
三层漏斗:JDK 版本(硬约束)→ 内存规模(G1 4-32GB)→ 业务特征(吞吐/延迟/空间)
关键可视化
GC 器演进主线
flowchart LR S["Serial<br/>JDK 1.2<br/>单线程"] --> P["ParallelGC<br/>JDK 5<br/>并行高吞吐<br/>JDK 8 默认"] P --> C["CMS<br/>JDK 5<br/>并发标记清除<br/>JDK 14 弃用移除"] C --> G["G1<br/>JDK 7<br/>Region 可预测停顿<br/>JDK 9+ 默认"] G --> Z["ZGC<br/>JDK 15 GA<br/>读屏障+多映射<br/>STW<1ms<br/>TB 级堆首选"] G --> Sh["Shenandoah<br/>JDK 11<br/>写屏障+Brooks 转发<br/>STW<10ms<br/>RedHat 主推"]
三层漏斗决策
flowchart TB L1["第一层:JDK 版本(硬约束)"] --> L1R["JDK 8 用不了 ZGC<br/>JDK 14+ CMS 被移除<br/>JDK 9+ 默认 G1<br/>JDK 21 引入分代 ZGC"] L1 --> L2["第二层:内存规模"] --> L2R["Serial:<1GB<br/>G1:4-32GB 最佳<br/>ZGC:4GB-16TB<br/>Shenandoah:32GB+"] L2 --> L3["第三层:业务特征"] --> L3R["批处理/后台:ParallelGC(吞吐优先)<br/>Web 服务:G1(推荐)<br/>低延迟+大堆:ZGC<br/>并发优先:Shenandoah"]
GC 器对比表
flowchart TB
subgraph Serial
S1["吞吐低/停顿长/空间高<br/>堆<1GB<br/>嵌入式、单核"]
end
subgraph Parallel
P1["吞吐高/停顿中/空间中<br/>堆 4-32GB<br/>批处理、后台任务"]
end
subgraph CMS
C1["吞吐中/停顿短但有碎片/空间中<br/>已弃用<br/>JDK 14 移除"]
end
subgraph G1
G1["吞吐中/停顿可预测/空间中<br/>堆 4-32GB<br/>Web 服务通用"]
end
subgraph ZGC
Z1["吞吐中/停顿极短<10ms/空间中<br/>堆 4GB-16TB<br/>大堆、低延迟"]
end
subgraph Shenandoah
Sh1["吞吐中/停顿短<10ms/空间中<br/>堆 32GB+<br/>并发优先"]
end核心调优参数
flowchart LR P["调优参数"] --> M["-Xms=-Xmx<br/>避免动态扩缩"] P --> M1["-XX:MaxGCPauseMillis<br/>G1 目标停顿"] P --> M2["-XX:ParallelGCThreads<br/>并行 GC 线程数"] P --> M3["-XX:ConcGCThreads<br/>并发 GC 线程数"] P --> L["GC 日志+JFR<br/>-Xlog:gc*<br/>关注 STW P99/FullGC 次数"]
知识关系
🔄 延伸(Extends)
暂无
🎯 概念
📏 规则
⚠️ 误区
🔍 追问
✨ 口诀
共 0 张卡,点击翻面