前言
cms是一個基於 標記-清除 算法的老年代垃圾回收器,綜合考慮多方因素結合多個垃圾回收算法組成的,適用場景:重視服務器響應速度,要求系統停頓時間最短。這裏要說明以下,這是一個老年代算法,年輕代怎麼處理?不回收了嘛?這裏其實年輕代是採用的其它算法,具體看策略,Java 參數可以選擇策略。這裏下文也會涉及到。
流程
- 1、初始標記(CMS initial mark)
“Stop The World”,僅僅只是標記一下 GC Roots 能直接關聯到的對象,還有遍歷新生代對象,標記可達的老年代對象;速度很快。
這些灰色的節點就是初始標記的節點。
- 2、併發標記(CMS concurrent mark)
進行 GC RootsTracing 的過程,繼續遞歸標記這些對象可達的對象,做可達性分析等
- 3、重新標記(CMS remark)
“Stop The World”,爲了修正併發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間一般會比初始標記階段稍長一些,但遠比並發標記的時間短。 - 4、併發清除(CMS concurrent sweep)
並行清理數據垃圾,回收內存。
耗時最長的是併發標記和併發清除,但併發標記和併發清除過程收集器線程都可以與用戶線程一起工作,所以,從總體上來說,CMS 收集器的內存回收過程是與用戶線程一起併發執行的。
優點缺點
優點:
- 併發收集
- 低停頓
缺點:
- CPU 資源消耗過大
併發設計會對CPU敏感,CMS 默認啓動的回收線程數:(CPU數量+3)/4,也就是當 CPU 在4個以上時,併發回收時垃圾收集線程不少於 25%。 - CMS 收集器無法處理浮動垃圾
併發期間不用暫停,那麼會導致這段期間產生的垃圾將不會被回收,只能下一次回收,這稱作浮動垃圾。 - 產生空間碎片
本質上是一個標記-清除 垃圾回收算法,意味着收集結束時會有大量空間碎片產生,給大對象分配空間帶來麻煩,如果老年代無空間可存放大對象,得不提前觸發一次 Full GC 。當然CMS也提供來一些Java 參數來幫助解決,比如頂不住壓力時開啓內存碎片的合併整理過程、多少次回收後使用該整理算法。
組合策略
CMS要跟一個年輕代算法組合一起使用,HotSpot共有7種垃圾收集器,3個新生代垃圾收集器,3個老年代垃圾收集器,以及G1,一共構成7種可供選擇的垃圾收集器組合。新生代與老年代垃圾收集器之間形成6種組合,每個新生代垃圾收集器都對應2種組合。下圖表示垃圾回收組合:
年輕代:
- Serial
- ParNew
- Parallel
CMS(不帶壓縮)可以與Serial和ParNew進行組合,共2種組合垃圾回收算法。
-XX:-UseParNewGC -XX:+UseConcMarkSweepGC
Serial (DefNew) + CMS(Concurrent Mark Sweep)
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
Parallel (ParNew) + CMS(Concurrent Mark Sweep) + Serial Old(Serial Mark Sweep Compact)