跳转到内容

收集器选型与演进

用途:为一个具体服务选 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 的公开技术文章