parnew 是专为多线程并发环境设计的新生代收集器,仅并行执行复制过程,仍需 stop-the-world;它与 cms 强绑定,分别负责年轻代和老年代回收,共同降低整体 gc 停顿。

ParNew 是专为多线程并发环境设计的新生代收集器,但它本身并不“并发”执行——每次回收仍是 Stop-The-World(STW),只是用多个线程并行完成复制过程。它和 CMS 的配合不是松耦合协作,而是强绑定的代际分工:ParNew 负责高频、低延迟的年轻代回收;CMS 负责低停顿的老年代回收。二者共同目标是压低整体 GC 停顿,尤其适用于对响应时间敏感的在线服务。
ParNew 的并行机制与线程控制
ParNew 本质是 Serial 收集器的多线程复刻,同样采用复制算法(Eden + Survivor 区间拷贝存活对象),区别仅在于回收时启用多条 GC 线程同步工作。
- 默认线程数等于 CPU 物理核心数,不区分超线程;单核或低负载场景下,线程切换开销可能反超收益,此时 Serial 更稳
- 线程数由 -XX:ParallelGCThreads=N 控制,该参数在 CMS 场景下被复用(注意:它不服务于 Parallel GC,此处易混淆)
- 建议设置 N ≤ CPU 核心数 × 0.75,避免线程争抢导致 STW 时间不降反升;JVM 不校验 N 是否超核数,但实际效果会劣化
与 CMS 的绑定逻辑与触发协同
ParNew 无法独立存在:JDK 8u40 起,单独启用 -XX:+UseParNewGC 会被忽略,并自动回退至 Serial,同时打印警告日志。它只在 -XX:+UseConcMarkSweepGC 生效时才被激活,作为 CMS 的“法定新生代搭档”。
- CMS 启动依赖老年代使用率阈值(-XX:CMSInitiatingOccupancyFraction,默认约 68%),而 ParNew 的频次间接反映晋升压力
- 若 ParNew 频繁发生(尤其伴随 “promotion failed” 日志),说明对象正快速晋升到老年代,CMS 并发周期可能跟不上,易触发 concurrent mode failure,最终退化为 Serial Old 全停顿 Full GC
- 二者无直接通信机制,调优关键在于降低晋升率:合理设置 -Xmn(新生代大小)、-XX:SurvivorRatio(Survivor 区比例),避免 Survivor 过小或老年代碎片化
典型失败信号与根因定位
日志中出现 “ParNew (promotion failed)” 并非 ParNew 自身出错,而是它在尝试晋升对象时受阻:
- Survivor 区已满,且老年代无连续空间接收晋升对象(CMS 清理后产生碎片,或已接近耗尽)
- -Xmn 设置过大,压缩了老年代可用空间,加剧晋升竞争
- -XX:SurvivorRatio 设得过高(如 12),导致单个 Survivor 区过小,无法容纳一次 Minor GC 的存活对象
- 应用存在内存泄漏,中短期对象持续堆积在老年代,CMS 来不及清理,最终触发担保失败
现状与替代建议
CMS 已在 JDK 9 标记为废弃、JDK 14 彻底移除,ParNew 也随之失去官方支持。当前新项目应优先选用 G1 或 ZGC;老系统维护中若仍沿用 ParNew+CMS,需重点关注晋升行为与碎片率,避免因参数误配引发级联停顿。不复杂但容易忽略。











