什么是CMS盔几?
CMS全稱叫做Concurrent Mark Sweep(并發(fā)標(biāo)記清除)煌寇,是一款以獲取最短回收停頓時間為目標(biāo)的老年代收集器,適合基于B/S系統(tǒng)的服務(wù)器上共郭,系統(tǒng)停頓時間更短,給用戶帶來較好的體驗(yàn)。
從名字(包含Mark Sweep)上就可以看出澈歉,CMS收集器使用“標(biāo)記-清除”算法實(shí)現(xiàn)的,它的運(yùn)作相對于其他垃圾收集器來說是比較復(fù)雜的又碌,整個過程分四個步驟,包括:
- 初始標(biāo)記 (CMS initial mark)
- 并發(fā)標(biāo)記 (CMS concurrent mark)
- 重新標(biāo)記 (CMS remark)
- 并發(fā)清除 (CMS concurrent sweep)
其中初始標(biāo)記和重新標(biāo)記需要“Stop The World”绊袋,初始標(biāo)記僅僅是標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對象毕匀,速度很快,并發(fā)標(biāo)記階段就是進(jìn)行GC RootsTracing的過程癌别,而并發(fā)標(biāo)記階段則是為了修正并發(fā)標(biāo)記期間因?yàn)橛脩舫绦蚶^續(xù)運(yùn)作而導(dǎo)致的標(biāo)記產(chǎn)生變動的那一部分對象的標(biāo)記記錄皂岔,這個階段的停頓時間一般會比初始標(biāo)記階段稍長一些,但遠(yuǎn)比并發(fā)標(biāo)記的時間短展姐,整個過程中耗時最長的并發(fā)標(biāo)記和并發(fā)清除可以和用戶線程一起工作躁垛,所以CMS收集器的內(nèi)存回收過程是與用戶線程一起并發(fā)執(zhí)行的
CMS收集器調(diào)優(yōu)
調(diào)優(yōu)CMS收集器時最緊要的的工作是要避免并發(fā)模式失效和晉升失敗剖毯,并發(fā)模式失效往往是由于CMS不能以足夠快的速度清理老年代空間:新生代進(jìn)行垃圾回收時候,CMS收集器計算發(fā)現(xiàn)老年代沒有足夠空間可以容納這些晉升對象教馆,不得不先對老年代進(jìn)行來及回收逊谋,初始時老年代ko空間中對象一個接一個有序排列的,當(dāng)老年代空間占用達(dá)到某個程度(默認(rèn)70%)時土铺,并發(fā)回收就開始了胶滋,一個收集器必須在老年代30%空間用盡之前,完成老年代空間的掃描及回收工作悲敷,如果并發(fā)回收再這場速度競賽中失利究恤,CMS就會發(fā)生并發(fā)模式失效
有以下途徑可以避免發(fā)生這種失效:
- 想辦法增大老年代空間,要么只移動部分的新生代對象到老年代后德,要么增加更多的堆空間部宿。
- 以更高的頻率運(yùn)行后臺回收線程。
- 使用更多的后臺回收線程探遵。
CMS收集器使用二個配置MaxGCPauseMllis=N和GCTimeRatio=N來確定使用多大的堆和多大的代空間窟赏。
1.給后臺線程更多的運(yùn)行機(jī)會
為了讓CMS收集器贏得這場賽跑妓柜,方法一就是更早的啟動并發(fā)收集器周期箱季,顯然的,CMS收集器在老年代空間占用達(dá)到60%是啟動并發(fā)收集棍掐,這個老年代空間占用到70%才啟動相比藏雏,前者完成垃圾收集的幾率更大
2.調(diào)整CMS后臺線程
每個CMS后臺線程都會100%地占用機(jī)器上的一個CPU,如果發(fā)生并發(fā)模式失效作煌,同同時又有額外的CPU周期可用掘殴,可以設(shè)置-XX:ConcGCThreads= N標(biāo)志,增加后臺線程數(shù)目粟誓。默認(rèn)情況下ConcGCThreads的值是根據(jù)parallelGCThreads標(biāo)志的值計算得到的
:ConcGCThreads = ( parallelGCThreads + 3 )/ 4
參考文獻(xiàn):
Java并發(fā)編程博客 - 不可錯過的CMS學(xué)習(xí)筆記
CMS并發(fā)失效與晉升失敗
深入理解JAVA虛擬機(jī)JVM高級特性與最佳實(shí)踐(第2版)
Java性能權(quán)威指南