天天看點

CMS前世今生

CMS一直是面試中的常考點,今天我們用通俗易懂的語言簡單介紹下。

垃圾回收器為什麼要分區分代?

CMS前世今生

如上圖:JVM虛拟機将堆記憶體區域分代了,先生代是朝生夕死的區域,老年代是老不死的區域,不同的年代對象有不同特性,是以需要不同的垃圾收集器去處理。如下圖,黑豎線左邊的區域都是分代垃圾收集器,G1之後記憶體就不分代了。

CMS前世今生

單線程垃圾收集器:Serial + Serial Old

Serial(SY),Serial Old(SO)是單線程垃圾收集器組合,垃圾收集線程是單線程的,随着現代記憶體區域越來越大,SY+SO組合已經越來越少了。垃圾收集的單線程需要STW時間無疑越長。這種組合比較合适較早JDK版本。如下圖,使用者線程表示應用程式處理過程,垃圾收集線程表示垃圾線程清理垃圾過程,此階段應用程式是需要等待垃圾線程STW的。

CMS前世今生

多線程垃圾收集器:PS+PO

前面我們說了,單線程垃圾收集器缺點就是當記憶體區域變大,收集效率會很低,那OK,搖身一變,如下圖,多線程垃圾處理器。

CMS前世今生

值得注意的是:PS+PO組合是JDK1.7,JDK1.8預設垃圾收集器。通過java -XX:+PrintCommandLineFlags指令可以在Dos界面檢視。如下圖,該指令可以檢視JVM初始化的預設參數。比如:-XX:InitialHeapSize表示初始化堆大小。

CMS前世今生

為啥蹦出來個CMS+ParNew

并行處理有了,CMS+ParNew又是幹嘛的?其實PO關注是吞吐量,而CMS關注是縮短STW時間。而CMS處理流程更複雜,至于ParNew,其實約等于PS,如果你注意最上面一個圖,你會發現PS年輕代無法和CMS組合。是以就多出來了一個ParNew。

介紹CMS階段

CMS,全名稱Concurrent Mark Sweep,中文釋義并發标記清除,從名字上可以看出算法思想使用标記清除算法,下面我們看看CMS簡化處理流程。

CMS前世今生
  • 初始标記。隻标記GC root可達的第一個節點。會短暫的STW。
  • 并發标記。使用者線程和垃圾線程同時進行。垃圾線程會繼續向下尋找GCroot,不會有STW。但也會有兩個問題。
    • 多标:之前不是垃圾,現線上程出棧引用斷開了變成了垃圾。也稱為浮動垃圾。
    • 錯标:之前已經被标注是垃圾,但現在重新引用。
  • 重新标記。STW時間一般低于200毫秒。
  • 并發清除。并發清除時,因為使用者線程和垃圾線程一起工作,如果CMS線程異常,可能會觸發SO單線程執行。程式可能會特别緩慢。

劣勢:碎片嚴重。

總結