用途:为一个具体服务选 GC,并解释现有停顿的成因
| 收集器 |
区域 |
算法 |
并发度 |
适用 |
| Serial / Serial Old |
年轻/老年 |
复制 / 标记-整理 |
单线程 STW |
小堆、客户端、容器极小规格 |
| Parallel Scavenge + Parallel Old |
年轻/老年 |
复制 / 标记-整理 |
多线程 STW |
吞吐优先,批处理 |
| CMS |
老年 |
并发标记清除 |
大部分并发 |
已废弃(JDK 14 移除),历史项目仍见 |
| G1 |
全堆(Region 化) |
复制 + 停顿预测模型 |
并发标记 + 并行整理 |
通用默认(JDK 9 起默认) |
| ZGC / Shenandoah |
全堆 |
并发整理 + 着色指针/读屏障 |
近乎全并发 |
大堆(数十 GB 以上)与低延迟要求 |
| Epsilon |
— |
不回收 |
— |
短生命周期任务、性能实验 |
- 堆划分为 Region,逻辑分代、物理不固定;维护各 Region 回收价值(垃圾占比 × 回收成本)的优先级列表。
- 停顿目标
-XX:MaxGCPauseMillis(默认 200ms)是软目标:G1 据此选择本轮回收的 Region 数量,目标设得过小会导致回收不足、频繁 GC 甚至 Full GC。
- 关键阶段:Young GC → 并发标记周期(初始标记在 Young GC 中借用)→ 混合回收(Mixed GC)→ 必要时 Full GC(单线程整理,是明显退化信号)。
- 调优抓手:
InitiatingHeapOccupancyPercent(触发并发标记的堆占比)、G1HeapRegionSize(大对象阈值)、分配速率与晋升速率监控。
- 目标是停顿与堆大小基本无关(亚毫秒级),代价是吞吐略降与更高的内存/CPU 开销。
- 依赖读屏障与着色指针完成并发整理;对指针密集、大堆、低延迟服务合适。
- JDK 21 起提供分代 ZGC,显著改善短生命周期对象的回收效率;使用前确认所用 JDK 版本能力。
| 约束 |
建议 |
| 堆 ≤ 4G、延迟不敏感 |
Parallel 或 G1 默认 |
| 通用在线服务、堆 4-32G |
G1,设合理停顿目标 |
| 堆 > 32G 或对 P99 停顿极敏感 |
ZGC(有分代能力时优先分代) |
| 批处理/离线,追求吞吐 |
Parallel,配合大 Young 区 |
| 容器内存极小 |
Serial,减少线程与元数据开销 |
| 误区 |
修正 |
| 照抄别人参数 |
参数必须对应自己的分配速率、堆大小与延迟目标 |
| 停顿目标越小越好 |
目标过小 → 回收量不足 → 总停顿反而上升 |
| 出现 Full GC 就换收集器 |
先查泄漏、大对象、晋升速率与元空间阈值 |
| 只看吞吐不看尾延迟 |
用 P99/P999 停顿与应用侧 P99 RT 共同评估 |
| 认为 G1 一定优于 Parallel |
吞吐型负载 Parallel 常更快 |
- OpenJDK G1、ZGC 官方文档与调优指南
- 《Java 性能权威指南》(Scott Oaks)GC 章节
- Azul 与 Red Hat 关于 ZGC/Shenandoah 的公开技术文章