CMS收集器的主要設計目標是:低應用停頓時間。它經過兩種方式實現這一目標:html
主要問題:因爲不壓縮帶來的老年代堆碎片,或者在對象分配率高的狀況下,均可能致使Full GC。java
CMS收集器的GC週期主要由7個階段組成,其中有兩個階段會發生stop-the-world,其餘階段都是併發執行的。(亦有4個階段、6個階段等說法)數據結構
初始化標記階段,是CMS GC的第一個階段,也是標記階段的開始。主要工做是標記可直達的存活對象。多線程
主要標記過程併發
程序執行狀況oracle
(Marked obj:老年代綠色圓點表示被初始化標記的對象。)jvm
併發標記階段,是CMS GC的第二個階段。ide
在該階段,GC線程和應用線程將併發執行。也就是說,在第一個階段(Initial Mark)被暫停的應用線程將恢復運行。ui
併發標記階段的主要工做是,經過遍歷第一個階段(Initial Mark)標記出來的存活對象,繼續遞歸遍歷老年代,並標記可直接或間接到達的全部老年代存活對象。線程
(Current obj:該對象的引用關係發生變化,對下一個對象的引用被刪除。)
因爲在併發標記階段,應用線程和GC線程是併發執行的,所以可能產生新的對象或對象關係發生變化,例如:
對於這些對象,須要從新標記以防止被遺漏。爲了提升從新標記的效率,本階段會把這些發生變化的對象所在的Card標識爲Dirty,這樣後續就只須要掃描這些Dirty Card的對象,從而避免掃描整個老年代。
在併發預清洗階段,將會從新掃描前一個階段標記的Dirty對象,並標記被Dirty對象直接或間接引用的對象,而後清除Card標識。
標記被Dirty對象直接或間接引用的對象:
清除Dirty對象的Card標識:
本階段儘量承擔更多的併發預處理工做,從而減輕在Final Remark階段的stop-the-world。
在該階段,主要循環的作兩件事:
具體執行多久,取決於許多因素,知足其中一個條件將會停止運行:
預清理階段也是併發執行的,並不必定是全部存活對象都會被標記,由於在併發標記的過程當中對象及其引用關係還在不斷變化中。
所以,須要有一個stop-the-world的階段來完成最後的標記工做,這就是從新標記階段(CMS標記階段的最後一個階段)。主要目的是從新掃描以前併發處理階段的全部殘留更新對象。
主要工做:
併發清理階段,主要工做是清理全部未被標記的死亡對象,回收被佔用的空間。
併發重置階段,將清理並恢復在CMS GC過程當中的各類狀態,從新初始化CMS相關數據結構,爲下一個垃圾收集週期作好準備。
參考
psy-lob-saw.blogspot.com/2014/10/the…
更多文章,請關注公衆號:二進制之路