JVM-CMS全過程分析

其實網上有很多這類的文章,但是主要最近閒來無事,就寫一下自己在經過了各類書籍的研究後得出的一些自己的見解。

那麼CMS的大部分流程其實都有說到,那麼我們就從每個細節開始講解一下吧。

1.初始標記
2.併發標記
3.重新標記
4.併發清除

一.首先是第一步:初始標記,該過程會導致STW,這個過程是爲了掃描JVM當中的根對象(GC roots)以及直接關聯的對象,所謂的根對象一般來說的話通常是指(1)棧中所使用到的對象。(2)本地方法所使用到的對象。(例如native)。(3)Class對象。(4)靜態+final變量。(5)老年代對象(並不是說所有老年代對象,是指card table中的老年代對象,也就是指那些有年輕代引用的老年代對象,這是種以空間換時間的方法,分代GC年輕代時,不用掃描老年代,節約時間)。等等(可以參考的文章)https://blog.csdn.net/xhh198781/article/details/42213847

那麼這個時候掃描的時候就有兩種方式,(1)廣度優先(2)深度優先。那麼CMS選擇的是深度優先,這樣的好處比較明顯,因爲計算機有一個預讀機制,那麼這個時候深度優先就會比廣度優先更有效率。那麼找到之後需要如何標記喃?

這個時候就會出現一種標記方法,三色標記法(黑白灰)。剛開始掃描一個對象的時候會先把它標記爲灰色,然後去遍歷其引用

(1)沒有引用了,那麼會把他變爲黑色。

(2)遍歷其引用,首先將他變爲黑色,然後將該引用變爲灰色,接着遍歷引用。

那麼JVM是如何處理顏色喃?

(1)黑:遍歷完畢,不是垃圾

(2)灰:正在遍歷

(3)白:垃圾

那麼初始標記只會有兩種顏色,黑色和灰色。那麼這個時候第一步就走完了。

二.併發標記。

就是併發標記第一步標記的對象,把目前存活的對象標記上黑色。

由於叫做併發標記,那麼何謂併發?

就是指GC線程和用戶線程一起運行。那麼中間就有可能出現對象關係發生改變的情況了。那麼我們舉個例子

下圖最開始的關係是 A -> B -> C(A擁有B的引用,B擁有C的引用)。

那麼在第二步剛好掃描到B的時候,用戶線程將關係變成了A ->C ,B變成無引用。

那麼這個時候C就可能在系統中找不到了,因爲A已經是黑色了,不會再根據A去搜索了。

所以這個時候CMS提供了一種write barrier

write barrier是指記錄當時引用的變化情況。

當整個環境中不存在灰色的時候就是重新標記的時候了。

三.重新標記

所謂的重新標記是指將write barrier中的關係變化修改到併發標記的三色標記當中,例如上圖,這個時候首先會進行STW,然後將C標記爲灰色,繼續遍歷即可。完成之後會進行下一步併發清除。

四.併發清除

併發清除是GC線程和用戶線程一起執行的,那麼這個時候新生成的對象是不會在這次GC範圍之中的,那麼就會有浮動垃圾。

那麼只會處理在這次GC中被標記爲白色的了。那麼這個時候如果白色仍然變爲了存活對象會怎麼辦喃,這個時候還是依靠writer barrier來保證清除掉的一定是垃圾。

如果只是標記清除即可,如果發生整理,和將年輕代移動到老年代的時候,就需要涉及到修改指針的問題了,

那麼流程大概是將該對象進行復制,並將其移動,在原來的位置處,記錄一個forward地址,該forward地址是移動後的位置,然後找到引用該對象的老年代以及當前一級引用對象,修改其引用地址即可,如果後續有對象引用該對象,那麼直接將後續對象的引用地址修改即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章