parallel scavenge不负责老年代回收,需搭配parallel old(标记-整理,碎片率≈0);cms自带老年代回收(标记-清除,碎片率高,长期运行可达60%)。

Parallel Scavenge 本身不负责老年代回收,它必须搭配老年代收集器使用;而 CMS 的老年代回收是其核心能力之一。两者在老年代内存碎片率上的差异,本质源于所采用的垃圾回收算法不同——Parallel Scavenge 默认搭档 Parallel Old(标记-整理),CMS 自带老年代回收(标记-清除)。因此,对比不是“Parallel Scavenge vs CMS”,而是Parallel Old vs CMS 在老年代的碎片行为。
算法决定碎片本质
CMS 使用标记-清除(Mark-Sweep)算法清理老年代:先标记存活对象,再直接清除所有未标记对象。这个过程不移动对象、不整理内存,导致大量不连续的空闲空间被遗留,即产生高内存碎片率。长期运行后,即使总空闲空间充足,也可能因无法找到足够大的连续块而触发 Full GC(尤其是分配大对象时)。
Parallel Old 使用标记-整理(Mark-Compact)算法:在标记存活对象后,会将它们向内存一端紧凑排列,然后清理边界以外的空间。这一过程主动消除碎片,老年代内存始终保持高度规整,碎片率极低(通常可视为接近 0)。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
压测中碎片率的典型表现
在持续运行、频繁晋升大对象的压测场景下:
- CMS 老年代碎片率会随时间推移持续上升,1 小时压测后碎片率常达 20%–40%,3 小时后可能突破 60%;触发 Concurrent Mode Failure 后退化为 Serial Old(单线程标记整理),碎片虽被临时清理,但 STW 时间剧增,且再次进入 CMS 循环后碎片快速复现。
- Parallel Old 在每次老年代 GC(如 PSFullGC)后,老年代内存几乎无碎片;即便压测 8 小时以上,碎片率仍稳定在 1% 以内。其代价是每次 GC 都需完整 STW,停顿时间明显长于 CMS 的并发阶段。
碎片对系统稳定性的影响差异
高碎片率不是静态指标,它直接影响内存分配成功率和 GC 行为稳定性:
- CMS 下,碎片率 > 30% 时,大对象直接分配失败概率显著升高,容易诱发 Promotion Failure 或担保失败,进而触发 Full GC,形成“碎片→Full GC→更碎片”的恶性循环。
- Parallel Old 几乎不因碎片引发异常分配失败;其风险集中在STW 时间不可控增长——当堆增大或对象生命周期变长,标记+整理耗时上升,可能超出预期停顿阈值,但不会因碎片本身导致 GC 频次异常增加。
如何验证当前使用的组合及碎片倾向
启动 Java 进程时添加以下 JVM 参数,即可在 GC 日志中明确识别:
-
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps:观察日志中 GC 名称,如PSYoungGen+ParOldGen表示 Parallel Scavenge + Parallel Old;ParNew+ConcurrentMarkSweep表示 CMS 组合(注意:Parallel Scavenge 与 CMS 不兼容,不能共存)。 - CMS 日志中若频繁出现
concurrent mode failure或promotion failed,是碎片压力的直接信号;Parallel Old 日志中若ParOldGen区 GC 后 used 空间分布紧密、max capacity 接近 committed,说明整理有效、碎片极少。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










