
Java主流垃圾回收器有6种:Serial、Parallel、CMS(已废弃)、G1、ZGC和Shenandoah;选择依据是应用运行环境,如机器配置与停顿要求,而非版本新旧。
Java里常见垃圾回收器有6种主流选择:Serial、Parallel、CMS(已废弃)、G1、ZGC 和 Shenan
doah。选哪个不看“新不新”,而要看你的应用跑在哪——是4核2G的后台小服务?还是堆内存80GB、要求停顿
关键不是“单线程 vs 多线程”,而是你是否在追求吞吐量,以及有没有多核可用。
Serial GC(-XX:+UseSerialGC)只适合单核 CPU 或极轻量场景(如嵌入式、单元测试JVM),它会全程 STW,但启动快、内存开销最小;Parallel GC(-XX:+UseParallelGC)是 JDK8/9 默认的 Server 模式收集器,目标明确:最大化吞吐量;它新生代+老年代都并行,但每次 GC 仍会 STW —— 所以如果你的接口 P99 延迟卡在 500ms,别怪 Parallel,它压根不是为低延迟设计的;G1(-XX:+UseG1GC)确实是 JDK9+ 的默认 GC,但它不是银弹——尤其在小堆或高分配速率场景下容易翻车。
Region,靠预测模型控制停顿时间(比如 -XX:MaxGCPauseMillis=200),但这个值只是“目标”,不是保证;Mixed GC,甚至退化成 Full GC,STW 时间飙升;-XX:+UseStringDeduplication(减少字符串重复)和 -XX:G1HeapRegionSize(避免 Region 过小导致元数据膨胀)。CMS 在 JDK14 彻底移除,别再用 -XX:+UseConcMarkSweepGC;ZGC 和 Shenandoah 虽强,但对 JDK 版本和 OS 有硬性要求(ZGC 要 JDK11+,Linux only;Shenandoah 在 OpenJDK 12+ 官方支持)。
-Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps;-XX:+UnlockExperimentalVMOptions(JDK17)或直接去掉(JDK21+),且不能与 UseCompressedOops 在大堆(>4TB)下共存;ZGC 默认启用并发类卸载(-XX:+ZClassUnloading),但某些老框架(如早期 Spring Boot 2.3)反射缓存未清理,会导致 Metaspace OOM;关掉它:-XX:-ZClassUnloading;Allocation Stall(应用线程等不到空闲 Region),照样卡住,这时得调 -XX:ZCollectionInterval 或加大堆。真正决定 GC 表现的,从来不是参数本身,而是对象生命周期分布和分配速率。上线前务必用真实流量压测,而不是只看 HelloWorld 的 GC 日志。一个没被压出来的 Concurrent Mode Failure,往往比选错 GC 更致命。