Parallel Scavenge适合高吞吐量的后台计算密集型任务、离线分析等场景,不适用于P99延迟敏感的API网关、实时推荐等;需成对启用Parallel Scavenge与Parallel Old,调参应围绕吞吐目标反推,优先使用-XX:GCTimeRatio=99。

Parallel Scavenge 适合什么场景
它专为「高吞吐量」设计,不是低延迟优先。如果你的服务端核心指标是单位时间处理请求数(比如批处理、ETL、报表生成),而不是单次响应快不快,Parallel Scavenge 才值得考虑。Web API 类服务通常不适合——哪怕你加了 -XX:+UseParallelGC,也容易因 STW 时间波动被监控告警盯上。
- 适用:后台计算密集型任务、离线分析、JVM 进程生命周期长且无强实时性要求
- 不适用:API 网关、实时推荐、金融交易链路等对 P99 延迟敏感的环节
- 注意:
Parallel Scavenge只管新生代,老年代默认配的是Parallel Old,两者必须成对启用,不能混搭 CMS 或 G1
关键参数怎么设才不翻车
调参不是填数字,而是围绕吞吐目标反推。JVM 不会自动帮你平衡 GC 频率和单次耗时,全靠你用参数锚定边界。
-
-XX:MaxGCPauseMillis=200是软目标,JVM 会尽力满足,但可能以更频繁 GC 为代价;设得太小(如 50)会让吞吐暴跌,甚至触发Allocation Failure频发 -
-XX:GCTimeRatio=99(即 GC 时间占比 ≤1%)比暂停时间更直接控制吞吐,推荐优先用这个;默认值是 99,别乱改低 -
-XX:InitialHeapSize和-XX:MaxHeapSize必须显式设置且相等,否则堆动态扩容会干扰吞吐稳定性 - 新生代大小别靠
-Xmn硬调,改用-XX:NewRatio=2更稳妥——它让 JVM 根据总堆比例算新生代,避免小堆下新生代过小引发ParNew promotion failed
常见错误现象和对应检查点
线上一开 Parallel Scavenge 就出问题,大概率不是收集器本身的问题,而是配置和应用行为没对齐。
- 日志里反复出现
Full GC (Ergonomics):说明对象晋升太快,老年代不够用;检查-XX:SurvivorRatio是否太小导致 Survivor 区撑不住,或业务有大对象直接进老年代(-XX:PretenureSizeThreshold未设) - GC 日志显示
PSYoungGen每次回收后 used 值几乎不变:新生代太小或对象存活率高,考虑增大-XX:NewRatio或排查是否有缓存类对象长期驻留 - 用了
-XX:+UseParallelGC却看到ParNew日志:说明你同时启用了 CMS(-XX:+UseConcMarkSweepGC),冲突了,删掉 CMS 相关参数 - 启动报错
Unrecognized VM option 'UseParallelOldGC':JDK 8u121+ 默认开启 Parallel Old,无需手动加;旧版本才需要显式加
和 G1 对比时容易忽略的细节
很多人换 Parallel Scavenge 是因为听说“G1 在大堆下 GC 不稳定”,但切换前得看清真实瓶颈在哪。
- G1 的
Concurrent Mode Failure多半是因为并发标记跟不上分配速度,而 Parallel Scavenge 遇到同样压力只会变慢(更多 Minor GC + Full GC),不会崩溃——但慢到不可接受时,你其实该优化对象生命周期,而不是换收集器 - Parallel Scavenge 没有记忆集(Remembered Set),所以跨代引用检查全靠扫描老年代,当老年代很大(>16GB)且对象图复杂时,Minor GC 的 STW 时间会明显增长,这点比 G1 更难预测
- 监控上看不到
G1 Evacuation Pause这种分阶段耗时,Parallel Scavenge 的 GC 日志只有PSYoungGen和ParOldGen两段,想定位卡点只能靠-XX:+PrintGCDetails -XX:+PrintGCTimeStamps配合时间戳差值算
吞吐量调优不是选对收集器就结束的事,Parallel Scavenge 把 GC 行为变得更“确定”,但也把调参责任全压到了人身上——参数之间互锁,改一个常要动三个,而且没有自适应调节能力。真要稳,得先让对象分配节奏可预期。










