CMS和ParNew收集器随笔

960 阅读2分钟

虽然CMS在JDK9已经被淘汰了,但是我们现在依然使用的CMS收集器。

-XX:PretenureSizeThreshold先说下这个参数的作用。默认值是0,0表示对象不管多大都优先在Eden区分配,如果不为0,大于这个值的对象将会分配置直接分配到老年代。这个参数只对ParNew和Serial收集器起作用。

对于大对象直接分配到老年代实际上是有两种情况:

  1. 在新生代分配失败的不持有任何对象大数组,直接分配到老年代。
  2. 大于-XX:PretenureSizeThreshold参数的对象。

CMS的使用场景

适用于GC停顿时间短的场.

缺点

因为CMS使用的标记-清除算法,当程序运行的时间长了,会产生内存碎片,导致触发FullGC.

CMS触发GC的时机

  1. 主动触发
  • CMS默认每隔两秒会进行一次检查,判断老年代使用率是否达到阈值,需要进行OldGC。

    -XX:CMSInitiatingOccupancyFraction:老年代使用阈值默认是92%。

    -XX:+UseCMSInitiatingOccupancyOnly:始终基于设定的阈值,不根据运行情况进行调整。如果没有 -XX:+UseCMSInitiatingOccupancyOnly 这个参数, 只有第一次会使用CMSInitiatingPermOccupancyFraction=92 这个值. 后面的情况会自动调整。

  • 晋升分配担保失败,触发GC。

  1. 被动触发
  • YGC过程发生Promotion Failed,进而对老年代进行回收。
  • System.gc()

被动触发需要对老年代进行压缩整理,由Serial Old处理,需要STW.

GC过程

  1. 初始标记:标记GCroots可以直达的对象。(STW)
  2. 并发标记:引用发生变化的对象所在的Card(这个Card不是Card Table)标记为Dirty
  3. 并发预处理:处理新生代对象对老年代的引用,重新扫描Dirty,清除Card标记。
  4. 可中止的并发预处理:处理Dirty,更新新生代对象对老年代的引用的情况,主要是等待一次YGC,这样对于重新标记阶段将会减轻负担
  5. 重新标记:增量更新,处理跨代引用。(STW)
  6. 并发回收:
  7. 重置资源

CMS性能调优

CMS垃圾收集器可能造成停顿的点

  1. YGC
  2. 初始标记阶段
  3. 重新标记阶段
  4. Concurrent mode failure导致使用Serial-old收集老年代停顿。
  5. Promotion Failed晋升失败,full gc停顿
  6. 元空间耗尽导致fullgc

针对Concurrent mode failure主要有两个方面原因导致

  1. 内存碎片
  2. 老年代空间较小,或者CMS收集不及时

这个时候,可以降低老年代的触发MinorGC的阈值,提前进行GC。或者适当增加老年代空间。

争对Promotion Failed问题可以调整From To空间大小,开启FullGC压缩等手段。