CMS垃圾回收失败类型主要是两种:并发失效和晋升失败
并发失效
在新生代(YoungGen)
发生垃圾回收时,达到晋升年龄的对象会被移动到老年代(OldGen)
中。
如果老年代没有足够的空间容纳这个晋升对象,CMS为了腾出老年代空间,就会从本来的MinorGC
退化成FullGC
。
MinorGC
只回收新生代,而FullGC
不仅回收新生代,而且还会回收老年代,永久区(PermGen)或元区(MetaSpace)空间回收也可能随FullGC
顺便执行。
本来只是简单的新生代回收工作扩大到老年代甚至更大。除此之外,老年代空间通常比新生代的Eden
和Survivor
区大得多,检查和清理无效对象的时间要多得多。
还有,FullGC
回收的同时,所有进程必须StopTheWorld
,并用单线程(SerialGC)
开始垃圾回收。导致本来可以并发的MinorGC变得缓慢无比。
晋升失败
晋升失败
同样是老年代导致的问题。
CMS开启新生代垃圾收集的时候,判断老年代似乎有足够空间容纳所有晋升对象。
然而晋升的时候才发现老年代的空间竟然都是碎片化的,根本容纳不了一个完整的晋升对象。
剩下出路只有内存整理。所有应用运行的线程停止,CMS开始对老年代进行整理和压缩。
空间压缩要通过移动里面的对象,令这些对象排列好,所以晋升失败比不需要移动对象的并发失效
更加浪费时间。
完成清理的堆空间变得规整和空余,继续运行应用。
调优
并发失效调优:
- 令老生代垃圾回收提早,增大回收频率
- 增大老年代空间
- 增大新生代空间,提高对象滞留时间,更多新对象被回收而不是晋升。
- 增加更多后台回收线程
晋升失败调优:
- 有难度,因为CMS本身不能规整
Compat
内存,只能退化到SerialGC来做 - 尝试用G1,G1的内存模型更加先进
网友评论