CMS并发失效与晋升失败

Posted by phantomVK on January 16, 2017

并发失效

新生代发生垃圾回收时,达到晋升年龄的对象会被移动到老年代。如果老年代没有足够空间容纳晋升对象,CMS为了获得老年代空间,就会从本来的MinorGC退化成FullGC开始垃圾回收。

MinorGC只回收新生代,而FullGC不仅回收老年代,新生代、永久区(PermGen)或元空间(MetaSpace)清理也随之执行。本来只是简单的新生代回收工作扩大到老年代甚至永久代。除此之外,老年代空间通常比新生代的EdenSurvivor区大得多,检查和清理无效对象的时间更多。

FullGC回收的同时,所有进程必须Stop The World,并用单线程开始垃圾回收。导致可以并发的MinorGC变得缓慢无比。

晋升失败

同样是老年代导致的问题。CMS开启新生代垃圾收集时,判断老年代似乎有足够空间容纳所有晋升对象。然而晋升过程发现老年代空间碎片化,无法容纳完整的晋升对象。

所以只能触发内存整理,停止所有运行线程,CMS开始对老年代进行整理和压缩。空间压缩要通过移动对象,把对象排列到新位置上,所以晋升失败比不需要移动对象的并发失效更浪费时间。完成清理的堆空间变得规整,并出现空余。

调优

并发失效调优手段:

  • 令老生代垃圾回收提早,提高回收频率;
  • 增大老年代空间,容纳更多对象;
  • 增大新生代空间,增加对象滞留时间,令新对象被回收而不是晋升;
  • 增加更多后台回收线程;

晋升失败调优:

  • 每次Full GC触发整理,或多次Full GC后触发一次