CMS垃圾收集器收集詳細步驟算法
標記GcRoots直接可達老年對象,新生代存活對象引用的老年代對象.整個過程在JDK1.7中是單線程的在JDK1.8中是多線程的(經過CMSParallelInitialMarkEnabled參數調整)。這個過程會致使STW。
從
初始標記
階段標記過的對象開始,標記其它存活對象,這個階段垃圾回收線程和應用線程同時運行。因爲是同時運行,應用線程還在跑,會致使對象的晉升,對象引用的變化,特殊對象直接分配到老年代。這些受到影響的老年代對象所在的Card會被標記成Dirty,用於從新標記階段掃描,老年代對象的Card被標記爲Dirty的可能緣由以下面綠線所示。
因爲上一個階段是併發執行的未標記的變化對象只是標記成了Dirty對象,尚未處理,預清理
就是來標記這些Dirty對象
。以下圖:在併發標記階段3號Card被標誌爲Dirty。這個階段是爲從新標記
階段作準備。
預清理將6號標誌爲存活對象多線程
這個階段也是爲從新標誌階段作準備,在進入從新標誌階段前,最好能進行一個Minor GC,將年輕代清理一遍, 這樣能夠清除大部分年輕代的對象(絕大部分年輕代對象朝生夕死),儘可能縮短
從新標記
階段停頓時間,CMS還提供了CMSScavengeBeforeRemark參數,能夠在進入從新標記以前強制進行依次Minor gc。
預清理
和可被終止的預清理
都是爲從新標誌
階段作準備,因爲從新標誌
階段會發生(STW),因此要保證盡肯能的停頓時間段,否則就會影響應用程序的用戶體驗。這個階段掃描的目標是:年輕代+GC Roots+Dirty老年代對象,這個階段是多線程的(XX:+CMSParallelRemarkEnabled)。
用戶線程被激活,那些未被標誌的對象會被清除。'
CMS垃圾收集器參數回到初始狀態,爲下一次垃圾收集作準備。
從新標記
停頓時間過長80%的時間花在從新標誌
階段,若是發現從新標誌
階段停頓時間過長,可嘗試添加-XX:+CMSScavengeBeforeRemark
,在從新標誌
以前作一次Minor GC
,目的是減小對老年代對象的無效引用,下降從新標誌
的開銷。
CMS是基於標記-清除算法的,CMS只會刪除垃圾對象,不會對內存空間作壓縮,會形成內存碎片。咱們須要用-XX:CMSFullGCsBeforeCompaction=n
參數來調整,含義是在上一次CMS併發執行事後,還要執行多少次Full GC
才作內存壓縮.
在CMS GC過程當中因爲應用程序也在跑,當年輕代滿了,執行了
Minor GC
這時候,須要將存活對象放入老年代,而此時老年代空間也不足,這時CMS尚未機會回收老年代。能夠設置如下兩個參數
CMS對內存的佔用率達到75%將啓動GC,默認爲92%,過高將致使
promotion failed
若是沒有設置UseCMSInitiatingOccupancyOnly
,只設置了CMSInitiatingOccupancyFraction
那麼JVM只在第一次使用,後續會進行自動調整。爲何要設置以上兩個參數,在垃圾收集階段,用戶線程還在運行,因此必需要留夠空間讓用戶線程運行。CMS前五個階段都是標記存活對象的,除了」初始標記」和」從新標記」階段會stop the word ,其它三個階段都是與用戶線程一塊兒跑的,就會出現這樣的狀況gc線程正在標記存活對象,用戶線程同時向老年代提高新的對象,清理工做尚未開始,old gen已經沒有空間容納更多對象了,這時候就會致使concurrent mode failure, 而後就會使用串行收集器回收老年代的垃圾,致使停頓的時間很是長。
CMSInitiatingOccupancyFraction參數要設置一個合理的值,設置大了,會增長concurrent mode failure發生的頻率,設置的小了,又會增長CMS頻率,因此要根據應用的運行狀況來選取一個合理的值。若是發現這兩個參數設置大了會致使full gc,設置小了會致使頻繁的CMS GC,說明你的老年代空間太小,應該增長老年代空間的大小了。併發
在進行Minor GC時,Survivor space放不下,對象只能放入老年代,而此時老年代也放不下,大多數狀況是老年代內存碎片太多,致使沒有連續的空間存放對象。
發生Minor GC時,若是對象過大(Survivor Space存放不下)基本上會放到老年代,這種現象被稱爲對象過早晉升,這將致使老年代被中短時間對象增張,肯能致使嚴重的性能問題。若是老年代也滿了,會觸發Full GC,這將會致使遍歷整個堆,晉升失敗。
-XX:CMSFullGCsBeforeCompaction=n
,有規律對內存進行整理減小內存碎片。XX:+UseConcMarkSweepGC
-XX:CMSFullGCsBeforeCompaction=n
Full GC
n 次後進行內存壓縮整理-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSInitiatingOccupancyOnly
內存佔用70%將觸發CMS GC
-XX:+CMSScavengeBeforeRemark
CMS GC前執行一次Minor GC