JVM 垃圾回收时产生的 concurrent mode failure 的原因是什么?

Sherwin.Wei Lv8

JVM 垃圾回收时产生的 concurrent mode failure 的原因是什么?

回答重点

concurrent mode failure 是在 Java 虚拟机使用 CMS(Concurrent Mark-Sweep)垃圾收集器 时的一种失败现象。当 CMS 在执行垃圾回收时,发现内存中的老年代(Old Generation)空间不足以继续分配新对象时,导致垃圾回收被迫转为 Full GC。

产生的原因

  • CMS 收集器是并发进行的,意味着它会与应用线程同时运行。然而,如果在 CMS 的并发回收阶段,还没有及时清理出足够的空间来满足新对象分配,就会出现 concurrent mode failure
  • 一旦发生 concurrent mode failure,JVM 会停止应用线程,进入 Full GC 以回收更多内存,显著影响程序性能。

扩展知识

CMS 垃圾收集器工作原理

CMS 工作原理主要分为以下四个阶段:

  • 初始标记(Initial Mark):标记与根对象直接关联的对象,需要短暂停顿。
  • 并发标记(Concurrent Mark):与应用线程并发运行,标记老年代中的存活对象。
  • 重新标记(Remark):修正并发标记期间发生变化的对象,再次短暂停顿。
  • 并发清理(Concurrent Sweep):清除未被标记的垃圾对象,与应用线程并发运行。

concurrent mode failure 的优化措施

  • 增大老年代内存:通过增加老年代的堆大小(通过 JVM 参数 -Xmx-XX:CMSInitiatingOccupancyFraction)来减少 CMS 的触发频率,从而避免老年代内存不足。
  • 调优 CMS 的触发阈值:可以调整 CMS 的回收触发点,参数 -XX:CMSInitiatingOccupancyFraction=<N> 控制了 CMS 在老年代占用达到 N% 时触发垃圾回收。适当提前触发垃圾回收可以减少发生 concurrent mode failure 的概率。
  • 碎片整理:CMS 不会自动整理碎片,但可以通过配置 -XX:+UseCMSCompactAtFullCollection 来在 Full GC 后进行碎片整理,避免碎片化导致的内存不足问题。
  • 增加年轻代大小:通过增加年轻代(Young Generation)的内存大小,减少对象频繁晋升到老年代,进而减少老年代的内存压力。

CMS 参数配置

1
2
3
4
5
# 启用 CMS 垃圾收集器,并调整其启动参数
java -XX:+UseConcMarkSweepGC \
-XX:CMSInitiatingOccupancyFraction=70 \
-XX:+UseCMSCompactAtFullCollection \
-Xmx4g -Xms4g YourApplication
Comments