Java里常见垃圾回收器有哪些_JavaGC策略对比说明

Java主流垃圾回收器有6种:Serial、Parallel、CMS(已废弃)、G1、ZGC和Shenandoah;选择依据是应用运行环境,如机器配置与停顿要求,而非版本新旧。

Java里常见垃圾回收器有6种主流选择:Serial、Parallel、CMS(已废弃)、G1、ZGC 和 Shenandoah。选哪个不看“新不新”,而要看你的应用跑在哪——是4核2G的后台小服务?还是堆内存80GB、要求停顿

怎么一眼判断该用 Serial 还是 Parallel?

关键不是“单线程 vs 多线程”,而是你是否在追求吞吐量,以及有没有多核可用。

  • Serial GC-XX:+UseSerialGC)只适合单核 CPU 或极轻量场景(如嵌入式、单元测试JVM),它会全程 STW,但启动快、内存开销最小;
  • Parallel GC-XX:+UseParallelGC)是 JDK8/9 默认的 Server 模式收集器,目标明确:最大化吞吐量;它新生代+老年代都并行,但每次 GC 仍会 STW —— 所以如果你的接口 P99 延迟卡在 500ms,别怪 Parallel,它压根不是为低延迟设计的;
  • 误区:很多人以为“开了多线程就一定比 Serial 快”。错。如果堆只有 512MB,Serial 可能比 Parallel 更快,因为 Parallel 启动线程、同步状态本身就有开销。

G1 是不

是“万能默认”?什么时候它反而更糟?

G1(-XX:+UseG1GC)确实是 JDK9+ 的默认 GC,但它不是银弹——尤其在小堆或高分配速率场景下容易翻车。

  • G1 把堆切成 Region,靠预测模型控制停顿时间(比如 -XX:MaxGCPauseMillis=200),但这个值只是“目标”,不是保证;
  • 当对象分配速率远高于回收速率(如突发大量短生命周期对象),G1 会频繁触发 Mixed GC,甚至退化成 Full GC,STW 时间飙升;
  • 小堆(
  • 必须配:-XX:+UseStringDeduplication(减少字符串重复)和 -XX:G1HeapRegionSize(避免 Region 过小导致元数据膨胀)。

CMS 已废弃,ZGC/Shenandoah 又太新?那生产环境到底怎么稳着用?

CMS 在 JDK14 彻底移除,别再用 -XX:+UseConcMarkSweepGC;ZGC 和 Shenandoah 虽强,但对 JDK 版本和 OS 有硬性要求(ZGC 要 JDK11+,Linux only;Shenandoah 在 OpenJDK 12+ 官方支持)。

  • 如果你用的是 JDK8/LTS,G1 是最现实的平衡选择,但务必开启日志:-Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
  • JDK17+ 生产环境推荐 ZGC,但注意:它要求 -XX:+UnlockExperimentalVMOptions(JDK17)或直接去掉(JDK21+),且不能与 UseCompressedOops 在大堆(>4TB)下共存;
  • 常见坑:ZGC 默认启用并发类卸载(-XX:+ZClassUnloading),但某些老框架(如早期 Spring Boot 2.3)反射缓存未清理,会导致 Metaspace OOM;关掉它:-XX:-ZClassUnloading
  • 别迷信“毫秒级停顿”——ZGC 的 STW 只剩初始标记和最终标记两个极短阶段,但若发生 Allocation Stall(应用线程等不到空闲 Region),照样卡住,这时得调 -XX:ZCollectionInterval 或加大堆。

真正决定 GC 表现的,从来不是参数本身,而是对象生命周期分布和分配速率。上线前务必用真实流量压测,而不是只看 HelloWorld 的 GC 日志。一个没被压出来的 Concurrent Mode Failure,往往比选错 GC 更致命。