CMS
是一個很好的並發垃圾收集器,但是使用過程中會產生兩個重要的問題。
- promotion failed 晉升失敗
- concurrent mode failure 收集器無法處理浮動垃圾
promotion failed 晉升失敗原因
該問題發生在
Minor GC
過程中,Survivor Space
放不下轉移的對象,老年代也放不下(promotion failed發生的時候老年代CMS還沒有機會進行回收,又放不下轉移到老年代的對象,下一步就會產生concurrent mode fialure
,發生STW降級為Serial Old)
下面是一條
promotion failed
失敗的日志
106.641: [GC 106.641: [ParNew (promotion failed): 14784K->14784K(14784K), 0.0370328 secs]106.678: [CMS106.715: [CMS-concurrent-mark: 0.065/0.103 secs] [Times: user=0.17 sys=0.00, real=0.11 secs]
(concurrent mode failure): 41568K->27787K(49152K), 0.2128504 secs] 52402K->27787K(63936K), [CMS Perm : 2086K->2086K(12288K)], 0.2499776 secs] [Times: user=0.28 sys=0.00, real=0.25 secs]
concurrent mode failure產生的原因
concurrent mode failure
是CMS
特有的錯誤,CMS
的垃圾清理線程和用戶線程是並行進行的. 老年代正在清理,從年輕代晉升了新對象,或者分配的大對象在新生代放不下,直接在老年代分配內存,這時老年代也放不下,則會拋出concurrent mode failure
concurrent mode failure的影響
老年代的垃圾收集器從
CMS
退化成Serial Old
,所有用戶線程被暫停,停頓時間變長。
解決方案
CMS觸發太晚
-XX:CMSInitiatingOccupancyFraction=N
是指設定CMS在對內存占用率達到N%的時候開始GC(因為CMS會有浮動垃圾,所以一般都較早啟動GC);
- 將:
-XX:CMSInitiatingOccupancyFraction=N
調小
空間碎片太多
開啟空間碎片整理,並將空間碎片整理周期設置在合理范圍,-
XX:CMSFullGCsBeforeCompaction
作用:設置在執行多少次Full GC后對內存空間進行壓縮整理。
- -XX:+UseCMSCompactAtFullCollection (空間碎片整理)
- -XX:CMSFullGCsBeforeCompaction=n
垃圾產生太快
- 晉升閾值太小
- Survivor空間過小
- Eden區過小,導致晉升速率過快
- 存在大對象