java基礎---JVM---CMS垃圾回收器



====簡述CMS垃圾回收器垃圾回收的幾個流程
 
CMS作用於老年代的垃圾回收,但是也會掃描新生代的內容
 
1.初始標記階段。用戶線程暫停,標記所有和根對象直接相連的對象。
 
2.並發標記階段。用戶線程起來,這個階段標記所有可到達的對象
 
3.預處理階段。因為用戶線程起來了,所以可能有修改對象或者新增的對象,這個階段就是標記從新生代轉移到老年代的對象,老年代新分配到的對象以及修改的對象等等。
因為下一個階段是重標記,必須做GC停頓來掃描新生代和老年代,如何讓這個停頓時間少,如何更快的掃描標記,就是本階段的任務,所以預處理對新生代和老年代都做了相應的處理。
-----預處理階段新生代的處理方式:1.進行minorGC        2.remark階段會並發掃描新生代,所以預處理會將新生代分塊,分別給多個線程處理這就是並發。
-----預處理階段老年代的處理方式:1.使用Card Table加速掃描,是一個字節數組。老年代分塊,每一塊關聯card table中一個字節。1.如果在並發標記階段對象被用戶線程修改了,就會標記成dirty card,預處理階段進行可達性標記,然后把dirty card標記清除,這樣並發標記階段修改的對象也會被標記;2.如果老年代引用到新生代,也可以通過cardTable快速掃描到。
 
4.重標記階段。暫停用戶線程,重新標記可到達對象。預處理后這個階段速度會加快。
 
5.並發清理的階段。用戶線程同時進行執行,產生新的垃圾。
 
6.重置。准備下個階段的垃圾回收。
 

===CMS會帶來什么問題呢?
1.並發的問題
CMS默認使用的GC線程數量為(CPU+3)/4,如果cpu數量少的時候比如只有兩個,就會有1個進行GC那么應用就會有百分50的性能下降會很明顯,但是當cpu數量上升的時候就不會有這種問題了。
 
2.並發的第二個問題。gc線程用戶線程同步執行,就會有浮動垃圾產生。同時需要給用戶線程提供執行的空間,也就是說不能等到老年代滿了才進行垃圾回收,默認是到達百分92進行老年代垃圾回收。當然這個參數是可以設置的。太小了會使得gc頻繁就會有停頓,太大了可能會導致用戶線程無法執行,因為需要的空間不夠,這個時候會導致使用串行回收器進行回收,停頓時間會更長。
 
3.標記清楚法帶來的問題:內存碎片,可能老年代剩余空間很大但是因為內存碎片的原因,沒有很大的連續內存空間,大對象進來可能就會觸發垃圾回收。CMS的解決方式是通過設置在進行幾次回收之后進行內存壓縮。
 

====如果要標記老年代的對象,需要掃描新生代嗎?如何加快新生代的掃描呢?預處理的階段如何控制呢?
 
要標記老年代的對象需要掃描新生代,要想加快新生代的掃描就要讓新生代里面的對象變少,也就是進行一次垃圾回收。
預處理階段因為用戶線程也在跑,那么對象會一直變化,總得要有個停下來的時候,這個時候可以設置參數讓它停下來。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM