跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

如何选择合适的Java垃圾回收器_G1/ZGC/CMS选型与对比

应换掉Parallel GC当应用有明确延迟要求(如P99<4GB)、对象生命周期差异大或GC pause频繁超500ms;此时G1或ZGC更合适,但需匹配JDK版本与平台。 什么时候该换掉默认的Parallel GC Java 11+ 默认用
Parallel GC
,吞吐量优先,但停顿时间不可控。如果你的应用有明确的延迟要求(比如接口 P99 4GB)、对象生命周期差异大(大量短命 + 少量长命对象),或者频繁出现
GC pause > 500ms
的告警,那就别硬扛了——
Parallel GC
不是万能的。 常见错误现象:
Full GC
频繁、
Metaspace OOM
伴随长时间 STW、监控里看到
G1 Evacuation Pause
比
Parallel GC
的
GC pause
更平稳但总耗时略高,这些都不是配置问题,是回收器不匹配。 堆 Parallel GC,简单稳定,没理由换 堆 4–16GB + 延迟敏感:直接考虑
G1 GC
,它比 CMS 更易用,且 Java 14 起 CMS 已被移除 堆 > 16GB + 要求亚秒级停顿(如金融实时风控、游戏服):ZGC 是更现实的选择,但注意它目前只支持 Linux/x64 和 Linux/AArch64 G1 GC 的关键参数不是调得越细越好
G1 GC
的设计目标是“可预测停顿”,不是“绝对最短停顿”。它的核心机制是分 Region + 并发标记 + 混合回收,所以参数调整必须围绕这个逻辑来,而不是照搬 CMS 或 Parallel 的思路。 容易踩的坑:
-XX:MaxGCPauseMillis
设得太低(比如 50ms),会导致 G1 过度拆分回收集、频繁触发 Young GC、反而增加 CPU 开销;设得太高(比如 1000ms),又失去 G1 的意义。 立即学习 “ Java免费学习笔记(深入) ”; 推荐起点:
-XX:+UseG1GC -XX:MaxGCPauseMillis=200
,再根据实际 GC 日志里的
G1 Evacuation Pause
实际耗时微调
-XX:G1HeapRegionSize
别乱动,默认值(2MB)覆盖绝大多数场景;手动设小了会增加 Region 数量,拖慢并发标记;设大了可能导致大对象直接进 Humongous 区,引发碎片和提前 Full GC 不要配
-XX:G1NewSizePercent
和
-XX:G1MaxNewSizePercent
除非你真看懂了 G1 的自适应年轻代策略——它本就会动态调整,强行锁死反而破坏平衡 ZGC 在 JDK 11–21 中的实际兼容性断层 ZGC 从 JDK 11 开始实验性支持,但直到 JDK 15 才转为正式特性,JDK 21 是当前 LTS 版本中 ZGC 最成熟的阶段。很多团队卡在 JDK 11/17 上想用 ZGC,结果发现功能残缺或 bug 明显。 Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 典型问题:
java.lang.OutOfMemoryError: Java heap space
在 ZGC 下可能不是内存真不够,而是
ZPage
分配失败(尤其在容器环境 cgroup v1 + 内存限制 tight 时);或者
Unsafe.allocateMemory
调用失败,报
std::bad_alloc
——这跟 ZGC 的元数据映射机制有关,不是代码问题。 JDK 11:仅支持 Linux/x64,无类卸载支持,
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
启动后仍可能因反射或 JNI 触发退回到 Serial GC JDK 17:支持 AArch64,但
ZUncommitDelay
默认值不合理,容易在低负载时过早释放内存,导致后续分配抖动 JDK 21:支持 Windows/AArch64,
-XX:+ZGenerational
(分代 ZGC)已稳定,但需额外启用,不默认开启 CMS 已死,但它的教训还在影响 G1/ZGC 配置 CMS 被移除不只是因为并发失败多,更是因为它把“并发标记”和“并发清除”割裂开,导致浮动垃圾难处理、无法压缩、对 CPU 亲和性差。现在很多人调 G1 或 ZGC 时,还在下意识模仿 CMS 的思路:比如拼命压低初始标记时间、回避混合回收、过度依赖
-XX:CMSInitiatingOccupancyFraction
类似的阈值思维。 真实情况是:G1 的混合回收(Mixed GC)本质就是“带压缩的 CMS 清除”,ZGC 的转移(Relocation)全程并发且自动触发——你不需要、也不应该去“预测”什么时候该回收,而应关注 GC 日志里是否持续出现
to-space exhausted
(ZGC)或
to-space overflow
(G1),那才是真正的瓶颈信号。 别再找“等效于 CMSInitiatingOccupancyFraction 的 G1 参数”——
G1
用
-XX:InitiatingHeapOccupancyPercent
,但它只触发并发标记开始,不控制回收时机 ZGC 完全没有“触发阈值”概念,它的回收由
alloc rate
和
gc cycle interval
共同驱动,日志里
Pause Mark Start
出现频率高,说明应用分配太快,不是 GC 配置错了,是对象生命周期或缓存策略该优化了 所有 GC 器都救不了内存泄漏,如果
jstat -gc
显示
MU
(Metaspace used)持续上涨,先查
Classloader
泄漏,别急着换 GC GC 选型不是调参比赛,是结合部署环境、JDK 版本、监控能力、故障响应习惯做的系统判断。ZGC 再快,也掩盖不了没开 GC 日志、看不懂
Unified JVM Logging
格式的问题。

相关文章