1. 程式人生 > >深入理解JVM(四)——各個版本提供的垃圾收集器

深入理解JVM(四)——各個版本提供的垃圾收集器

上一篇將的回收演算法是記憶體回收的方法論,本篇講垃圾收集器的具體實現,Java虛擬機器規範並沒有對齊做出規定和限制,所以不同廠商,不同版本的虛擬機器,垃圾收集器有很大的區別。

收集器名稱 區域 說明
Serial 新生代 單執行緒,GC時必須停止其它執行緒直到收集結束;JVM執行在client模式下新生代的預設收集器,簡單有效;採用複製演算法
ParNew 新生代 Serial收集的多執行緒版,保留Serial的引數控制,演算法等,暫停所有使用者執行緒,採用複製演算法;JVM執行在server的首先的新生代收集器;只有它能和CMS配合工作
Parallel Scavenge 新生代 採用複製演算法,並行的多執行緒收集器,與ParNew不同的是,關注點不是停頓時間,而是可控制的吞吐量,即執行使用者程式碼的時間/(執行使用者程式碼的時間+垃圾收集的時間)。可設定最大GC時間和吞吐量大小等引數,也可以讓JVM自適應調整策略
G1 新生代/老年代 收集器最前沿版本,JDK 1.7,代替CMS的新產品
CMS 新生代 concurrent Mark Sweep,已獲取最短回收停頓為目標,大部分的網際網路站及服務端採用的方式,標記-清除演算法
Serial Old(MSC) 老年代 Serial的老年版,單執行緒收集器,採用標記-整理演算法,主要是client模式的JVM使用
Parallel Old 老年代 Parallel Scavenge的老年版,多執行緒,標記整理演算法

並行(Parallel):指多條垃圾收集執行緒並行工作,但此時使用者執行緒仍然處於等待狀態
併發(Concurrent):指使用者執行緒和垃圾收集執行緒同時執行(但不一定是並行的,可能是交替執行),使用者程式繼續執行,而垃圾收集程式執行在另外的CPU上。

CMS

  1. 初始標記(stop the world)
    單執行緒,僅僅關聯GC Roots能直接關聯到的物件,速度很快
  2. 併發標記
    多執行緒,和使用者執行緒併發, 進行GC Roots Trancing的過程
  3. 重新標記 (stop the world)
    多執行緒,為了修正併發標記期間因使用者程式繼續執行而導致的標記產生變動的那一部分物件,比初始標記略長,但遠比並發標記短
  4. 併發清除
    多執行緒,和使用者執行緒併發

3個明顯的缺點
1. CMS收集器對CPU資源非常敏感,當然面向併發的設計都對資源敏感,會佔用一部分的執行緒,影響應用程式,預設啟動(CPU數量+3)/4個回收執行緒。
2. CMS收集器無法處理浮動垃圾。併發清理過程中,使用者執行緒還在執行,伴隨執行就會有新的垃圾產生,這部分出現在標記之後,CMS無法清除,只能等待下一次GC。CMS為了滿足併發的需求,需要預留記憶體空間。
3. 標記-清理演算法導致老年代空間碎片化,CMS提供引數解決,在Full GC前,開啟記憶體碎片的合併整理過程。

G1

G1收集器的運作

  1. 初始標記
    單執行緒,僅僅關聯GC Roots能直接關聯到的物件,速度很快;修改TAMS(Next Top at Mark Start),為了下一階段使用者程式併發執行,能在正確可用的Region上建立物件
  2. 併發標記
    同CMS,並且虛擬機器記錄將併發標記時間物件變化記錄線上程Remembered Set Logs中
  3. 最終標記
    同CMS,將Remembered Set Logs裡面的資料合併到Remembered Set中
  4. 篩選回收
    標記-整理演算法,Region

G1具備一下特點
1. 並行與併發,充分利用多CPU和多核的硬體條件,縮短stop the world的時間,可以通過併發的方式讓Java程式繼續執行
2. 分代收集,不需要與其它收集器配合,獨立管理GC堆,採用不同的方式管理不同GC年齡的物件
3. 空間整合,與CMS不同,採用的是標記-整理演算法,從區域性上看是通過複製演算法實現的
4. 可預測的停頓, G1追求低停頓外,還建立了可預測的停頓時間模型,能讓使用者明確在一個長度為M毫秒的時間片斷內,消耗在垃圾收集上的時間不超過N毫秒

垃圾收集器的組成

不同的垃圾收集器可以互相搭配使用,雖然我們對垃圾收集器進行比較,但是目前為止還沒有最好的垃圾收集器出現,更加沒有萬能的垃圾蒐集器。以下未列舉的即為不可組合使用。

以下時各種垃圾收集器的搭配使用

新生代 老年代 說明
Serial Serial Old(MSC) 新生代採用複製演算法,暫停所有使用者執行緒,單執行緒;老年代採用標記-整理演算法,暫停所有使用者執行緒,單執行緒
Serial CMS 新生代採用複製演算法,暫停所有使用者執行緒,單執行緒;老年代,採用CMS收集器,初始標記(單執行緒,stopTheWorld),重新標記(併發標記),重新標記(多執行緒,stopTheWorld),並行清除(並行清理,標記-清理演算法)
ParNew Serial Old(MSC) 新生代採用複製演算法,stopTheWorld,多執行緒;老年代MSC同上
ParNew CMS 新生代同上ParNew,老年代同上CMS
Parallel Scavenge Serial Old(MSC) Parallel Scavenge收集方式和ParNew一致,重點關注吞吐量,但被MSC限制
Parallel Scavenge Parallel Old 老年代,多執行緒,標記-整理演算法,吞吐量優先組合
G1 G1 Java堆的記憶體佈局有很大的不同,劃分成多個大小相等的獨立區域Region,新生代和老年代不在物理隔離,能有效避免整個Java堆全區域的GC