CMS存在的問(wèn)題
概述
CMS 是老年代垃圾回收算法魁蒜,通過(guò)標(biāo)記-清除的方式眼耀,=意在通過(guò)并發(fā)的方式適度減少吞吐量较雕,減少用戶線程停頓時(shí)間结执。
CMS收集器對(duì)處理器資源非常敏感
CMS的在垃圾清除是使用并發(fā)清除的,如果處理器核數(shù)不高的情況下蔽介,垃圾回收會(huì)造成很高的負(fù)載摘投。
并發(fā)回收造成的內(nèi)存不足
造成原因
在CMS的并發(fā)標(biāo)記和并發(fā)清理階段,用戶線程是還在繼續(xù)運(yùn)行的虹蓄,程序在運(yùn)行自然就還會(huì)伴隨有新的垃圾對(duì)象不斷產(chǎn)生犀呼,而這部分的垃圾對(duì)象是出現(xiàn)在標(biāo)記過(guò)程結(jié)束以后,CMS無(wú)法在當(dāng)次收集中處理掉它們薇组,只好留在下次垃圾收集時(shí)再清理掉外臂。這樣的垃圾就叫做浮動(dòng)垃圾。由于垃圾收集和用戶線程是并發(fā)執(zhí)行的律胀,因此CMS收集器不能像其他收集器那樣幾乎填滿了再進(jìn)行收集宋光,需要預(yù)留一些空間用來(lái)保存用戶新創(chuàng)建的對(duì)象。
如何處理
在JDK1.5之前老年帶使用了68%空間后就會(huì)激活CMS收集累铅。
如果實(shí)際應(yīng)用中可以適當(dāng)調(diào)整參數(shù)-XX:CMSInitiatingOccu-pancyFraction 的值來(lái)提高CMS的觸發(fā)百分比,降低內(nèi)存回收頻率獲得更好的性能站叼。
到了JDK6 CMS收集器的啟動(dòng)閥值就已經(jīng)默認(rèn)提升到92%娃兽。
存在問(wèn)題
如果預(yù)留空間不夠怎么辦?
首先要確定這是個(gè)小概率事件尽楔,其次JVM對(duì)著的情況處理如下:
- CMS垃圾回收?qǐng)?bào)錯(cuò)(Concurrent Model Failure) 并發(fā)失敗投储。
- 啟動(dòng)后備預(yù)案:凍結(jié)用戶線程的執(zhí)行,臨時(shí)啟用Serial Old收集器來(lái)重新進(jìn)行老年代的垃圾收集阔馋。(這樣的話時(shí)間就會(huì)變得很長(zhǎng))
內(nèi)存碎片問(wèn)題
由于CMS老年代使用標(biāo)記-清除回收策略玛荞,因此會(huì)有內(nèi)存碎片問(wèn)題。當(dāng)碎片過(guò)多時(shí)呕寝,將會(huì)給大對(duì)象分配帶來(lái)麻煩勋眯,往往會(huì)出現(xiàn)老年代還有很多空間但就已經(jīng)不能保存對(duì)象了。不得不提前觸發(fā)一次Full GC下梢。為了解決這個(gè)問(wèn)題客蹋,CMS收集器提供了-XX:UseCMSCompactAtFullCollection開(kāi)關(guān)參數(shù),用于在CMS收集器不得不進(jìn)行Full GC時(shí)開(kāi)啟內(nèi)存碎片的合并整理過(guò)程孽江。 有參數(shù)可以配置有多少次Full GC會(huì)堆內(nèi)存碎片進(jìn)行整理(-XX:CMSFullGCsBeforeCompaction)
參考:深入理解java虛擬機(jī) - 第三版