离线处理应选parallel gc,因其吞吐量优先、多线程并行、stw高效;在线处理需低延迟,中小堆用parnew+cms,大堆用g1,超低延迟选zgc或shenandoah。

离线处理和在线处理对JVM垃圾回收器的要求差异显著,核心在于响应延迟容忍度、吞吐量优先级以及系统资源稳定性。选错回收器,轻则GC频繁拖慢批量任务,重则导致在线服务超时雪崩。
离线批处理场景:吞吐量优先,接受较长STW
离线任务(如夜间ETL、报表生成、模型训练)通常运行在固定窗口内,不直面用户,更看重单位时间内完成的计算量。
- 推荐使用 Parallel Scavenge + Parallel Old 组合:专为吞吐量设计,通过多线程并行回收新生代与老年代,最大化CPU利用率;可通过
-XX:MaxGCPauseMillis放宽停顿限制,让JVM自动调优吞吐目标 - 堆内存建议设为固定大小(
-Xms = -Xmx),避免运行中动态扩容触发额外Full GC - 避免启用CMS或G1——它们的并发阶段会争抢CPU资源,反而降低整体吞吐;ZGC/Shenandoah的元数据开销也不必要
在线服务场景:低延迟敏感,需控制STW时间
Web API、实时风控、消息推送等在线系统要求毫秒级响应,不能容忍几百毫秒以上的卡顿。
- 中小堆(≤4GB)且JDK8环境:可选用 ParNew + CMS,CMS在老年代采用并发标记清除,大幅缩短Full GC停顿;但需监控碎片率,防止并发模式失败(Concurrent Mode Failure)触发Serial Old回退
- 大堆(≥6GB)或JDK9+:首选 G1,通过Region分区与预测式停顿模型(
-XX:MaxGCPauseMillis=200)主动控制GC耗时;配合-XX:G1HeapRegionSize调整Region大小,减少大对象直接入老年代 - 超低延迟要求(如高频交易、实时推荐):考虑 ZGC(JDK11+)或 Shenandoah(JDK12+),STW全程控制在10ms内,且停顿时间基本不随堆增大而增长
混合负载场景:避免回收器“一刀切”
同一JVM同时承载定时批处理与常驻API(如Spring Boot Admin集成调度),需平衡矛盾需求。
- 不建议混用不同回收策略——例如在G1上强行开启CMS参数,会导致JVM启动失败或行为不可控
- 更可行的解法是物理隔离:批处理任务单独启进程,用Parallel GC;在线模块用G1/ZGC;通过脚本或容器编排区分资源
- 若必须共存,优先按在线部分定回收器(如G1),再通过
-XX:InitiatingOccupancyFraction提前触发Mixed GC,减少批处理期间的老年代压力
回收器搭配与验证要点
实际落地时,仅选型不够,还需验证是否真正适配业务特征。
- 开启GC日志:
-Xlog:gc*:file=gc.log:time,tags,level(JDK10+),重点观察Minor GC频率、Full GC次数、平均停顿与最大停顿 - 离线任务关注 总GC时间占比(应<5%),在线服务关注 99分位GC停顿(如P99<100ms)
- CMS需警惕“promotion failure”(晋升失败),G1需防范“evacuation failure”,这些都比单纯停顿超标更危险,需结合堆使用率与对象晋升速率综合判断











