18910140161

关于CMS收集器的问题?

顺晟科技

2021-06-28 19:39:24

114

在JVM第三版中,书中说CMS收集器无法清除“浮动垃圾”,可是运作过程中的重新标记不就是为了清除浮动垃圾才有的吗?为什么会这样说呢? [图片] [图片…

我们从CMS收集器产生的问题和解决方案产生的问题1:

提升失败

在 Minor GC 过程中,Survivor Unused 可能不足以容纳 Eden 和另一个 Survivor 中的存活对象, 那么多余的存货对象将被移到老年代, 称为过早提升(Premature Promotion)。 这会导致老年代中短期存活对象的增长, 可能会引发严重的性能问题。再进一步,如果老年代没有足够的空间放下这些存活对象,或者老年代有足够的空间,但是由于碎片较多,这时如果新生代要转移到老年带的对象比较大,所以,必须尽可能提早触发老年代的CMS回收来避免这个问题(promotion failed时老年代CMS还没有机会进行回收,又放不下转移到老年带的对象,因此会出现下一个问题concurrent mode failure,需要stop-the-wold GC- Serail Old)。解决方案:针对一些大的朝生熄灭的对象,Surivor空间存放不下,就会存放到老年代,针对这种情况,可以扩大Survivor空间。老年代空间碎片,无法放下大对象,就在进行一定次数的Full GC(标记清除)的时候进行一次标记整理算法。产生的问题2:

并发模式失败

由于cms的无法处理浮动垃圾(Floating Garbage)引起的。这个跟cms的机制有关。cms的并发清理阶段,用户线程还在运行,因此不断有新的垃圾产生,而这些垃圾不在这次清理标记的范畴里头,cms无法在本次gc清除掉,这些就是浮动垃圾。由于这种机制,cms年老代回收的阈值不能太高,否则就容易预留的内存空间很可能不够(因为本次gc同时还有浮动垃圾产生),从而导致concurrent mode failure发生。可以通过-XX:CMSInitiatingOccupancyFraction的值来调优。

解决方案:CMS并发清理阶段,用户线程在年轻代中产生大量对象,大量年轻代中的对象要提升到老年代,老年代的清理速度赶不上年轻代的提升速度,就会造成concurrent mode failure,针对这个问题,扩大年轻代的空间,提升年轻代的晋升阈值扩大老年代的空间存放年轻代要晋升的对象,设置 CMS 垃圾收集在老年代占比达到多少时启动来减少问题发生频率(越早启动问题发生频率越低,但是会降低吞吐量,具体得多调整几次找到平衡点)CMS并发清理阶段,年轻代提升上来的大对象,老年代碎片化严重,存放不下,针对这个问题,一定次数的Full GC(标记清除)的时候进行一次标记整理算法。总:promotion failed造成Full GC,也可能会进一步造成 concurrent mode failure注意要尽量避免concurrent mode failure,因为这样会是 CMS收集器转化为Serial Old收集器,Serial Old收集器虽然会压缩老年代空间,但是这个收集器整个过程都是STOP THE World
相关文章
我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航