CMS爲何採用標記-清除算法

年老代併發收集器-CMS

clipboard.png

-XX:+UseConcMarkSweepGC
新生代:複製算法,默認搭配ParNewGC,並行
年老代:標記-清除,併發(若是發生Concurrent Mode Fail,則使用SerialOld作後備收集器)java

並行與併發的區別

clipboard.png

CMS的執行週期

clipboard.png

  • 初始標記:STW,單線程,因爲是從GCRoot尋找直達的對象,速度快算法

  • 併發標記:與應用線程一塊兒運行,是CMS最主要的工做階段,經過直達對象,掃描所有的對象,進行標記多線程

  • 從新標記:STW,修正併發標記時因爲應用程序還在併發運行產生的對象的修改,多線程,速度快,須要全局停頓併發

  • 併發清除:與應用程序一塊兒運行,爲什麼採用清除算法?CMS主要關注低延遲,於是採用併發方式,清理垃圾時,應用程序還在運行,如何採用壓縮算法,則涉及到要移動應用程序的存活對象,此時不停頓,是很難處理的,通常須要停頓下,移動存活對象,再讓應用程序繼續運行,但這樣停頓時間變長,延遲變大,因此CMS採用清除算法。性能

後備收集器:SerialOld

clipboard.png

併發GC,吞吐量降低,採用標記清除,碎片多,佔用額外內存,不能在堆空間滿時清理,觸發GC:
清理時,應用程序還在運行此時若是預留的空間不夠應用程序申請的空間的話,則會觸發Concurrent Mode Fail,此時便會啓用後備收集器:SerialOld進行GC,產生全局停頓spa

併發模式失敗(Concurrent Mode Failure)

CMS收集器沒法處理浮動垃圾(Floating Garbage),可能出現「Concurrent Mode Failure」失敗而致使另外一次Full GC的產生。線程

(1)若是對象提高到年老代的速度太快,而CMS收集器不能保持足夠多的可用空間時,就會致使年老代的運行空間不足;
(2)當年老代的碎片化達到某種程度,使得沒有足夠空間容納重新生代提高上來的對象時,也會發生併發模式失敗。設計

當發生併發模式失敗時,年老代將進行垃圾收集以釋放可用空間,同時也會整理壓縮以消除碎片,這個操做須要中止全部的java應用線程,而且須要執行至關長時間。3d

浮動垃圾

因爲CMS併發清理階段用戶線程還在運行着,伴隨程序運行天然就還會有新的垃圾不斷產生,這一部分垃圾出如今標記過程以後,CMS沒法在當次收集中處理掉它們,只好留待下一次GC時再清理掉。這一部分垃圾就稱爲「浮動垃圾」。對象

CMSInitiatingOccupancyFraction

也是因爲在垃圾收集階段用戶線程還須要運行,那也就還須要預留有足夠的內存空間給用戶線程使用,所以CMS收集器不能像其餘收集器那樣等到老年代幾乎徹底被填滿了再進行收集,須要預留一部分空間提供併發收集時的程序運做使用

在JDK 1.5的默認設置下,CMS收集器當老年代使用了68%的空間後就會被激活,這是一個偏保守的設置,若是在應用中老年代增加不是太快,能夠適當調高參數-XX:CMSInitiatingOccupancyFraction的值來提升觸發百分比,以便下降內存回收次數從而獲取更好的性能,

在JDK 1.6中,CMS收集器的啓動閾值已經提高至92%。要是CMS運行期間預留的內存沒法知足程序須要,就會出現一次「Concurrent Mode Failure」失敗,這時虛擬機將啓動後備預案:臨時啓用Serial Old收集器來從新進行老年代的垃圾收集,這樣停頓時間就很長了。

因此說參數-XX:CMSInitiatingOccupancyFraction設置得過高很容易致使大量「Concurrent Mode Failure」失敗,性能反而下降。

CMS內存整理

CMS是一款基於「標記—清除」算法實現的收集器,這意味着收集結束時會有大量空間碎片產生。

空間碎片過多時,將會給大對象分配帶來很大麻煩,每每會出現老年代還有很大空間剩餘,可是沒法找到足夠大的連續空間來分配當前對象,不得不提早觸發一次Full GC。

爲了解決這個問題,CMS收集器提供了一個-XX:+UseCMSCompactAtFullCollection開關參數(默認就是開啓的),用於在CMS收集器頂不住要進行FullGC時開啓內存碎片的合併整理過程,內存整理的過程是沒法併發的,空間碎片問題沒有了,但停頓時間不得不變長。

虛擬機設計者還提供了另一個參數-XX:CMSFullGCsBeforeCompaction,這個參數是用於設置執行多少次不壓縮的Full GC後,跟着來一次帶壓縮的(默認值爲0,表示每次進入Full GC時都進行碎片整理)。

Promotion Failure

過早提高(Premature Promotion),MinorGC過程當中,Survivor可能不足以容納Eden和另一個Survivor中存活的對象,若是Survivor中的存活對象溢出,多餘的對象將被移到年老代。

在MinorGC過程當中,若是年老代滿了沒法容納更多的對象,則MinorGC以後,一般會進行FullGC,這將致使遍歷整個java堆,這稱爲提高失敗(Promotion Failure)

相關文章
相關標籤/搜索