CMS與G1-接上一篇
垃圾回收-淺談JVM垃圾演算法
首先要知道 Stop the world的含義:不管選擇哪種GC演算法,stop-the-world都是不可避免的。Stop-the-world意味著從應用中停下來並進入到GC執行過程中去。一旦Stop-the-world發生,除了GC所需的執行緒外,其他執行緒都將停止工作,中斷了的執行緒直到GC任務結束才繼續它們的任務。GC調優通常就是為了改善stop-the-world的時間
-
CMS
CMS收集器是一種以獲取最短回收停頓時間為目標的收集器,CMS收集器是基於“”標記–清除”(Mark-Sweep)演算法實現的,整個過程分為四個步驟1. 初始標記 (Stop the World事件 CPU停頓, 很短) 初始標記僅標記一下GC Roots能直接關聯到的物件,速度很快; 2. 併發標記 (收集垃圾跟使用者執行緒一起執行) 初始標記和重新標記任然需要“stop the world”,併發標記過程就是進行GC Roots Tracing的過程; 3. 重新標記 (Stop the World事件 CPU停頓,比初始標記稍微長,遠比並發標記短)修正併發標記期間因使用者程式繼續運作而導致標記產生變動的那一部分物件的標記記錄,這個階段的停頓時間一般會比初始標記階段稍長一些,但遠比並發標記時間短 4. 併發清理 -清除演算法;
整個過程中耗時最長的併發標記和併發清除過程收集器執行緒都可以與使用者執行緒一起工作,所以,從總體上來說,CMS收集器的記憶體回收過程是與使用者執行緒一起併發執行的。
初始標記:僅僅是標記一下GC roots 能直接關聯的物件,速度很快 (何為GC roots :
在Java語言中,可作為GC Roots的物件包括4種情況:
a) 虛擬機器棧中引用的物件(棧幀中的本地變量表);
b) 方法區中類靜態屬性引用的物件;
c) 方法區中常量引用的物件;
d) 本地方法棧中JNI(Native方法)引用的物件。
優點: 併發收集, 低停頓
缺點: 因為第四步是GC執行緒與使用者執行緒並行執行, 所以產生的垃圾無法及時回收. 也就是浮動垃圾.
2. G1 標記整理
G1雖然也把記憶體分成了這三大類,但是在G1裡面這三大類不是涇渭分明的三大塊記憶體,G1把記憶體劃分成很多小塊, 每個小塊會被標記為E/S/O中的一個,可以前面一個是Eden後面一個就變成Survivor了。
由於把三塊記憶體變成了幾百塊記憶體,記憶體塊的粒度變小了,從而可以垃圾回收工作更徹底的並行化.
G1的另一個顯著特點他能夠讓使用者設定應用的暫停時間,為什麼G1能做到這一點呢?也許你已經注意到了,G1回收的第4步,它是“選擇一些記憶體塊”,而不是整代記憶體來回收,這是G1跟其它GC非常不同的一點,其它GC每次回收都會回收整個Generation的記憶體(Eden, Old), 而回收記憶體所需的時間就取決於記憶體的大小,以及實際垃圾的多少,所以垃圾回收時間是不可控的;而G1每次並不會回收整代記憶體,到底回收多少記憶體就看使用者配置的暫停時間,配置的時間短就少回收點,配置的時間長就多回收點,伸縮自如。
回收的四個步驟:
1. 初始標記(stop the world事件 CPU停頓只處理垃圾);
2. 併發標記(與使用者執行緒併發執行);
3. 最終標記(stop the world事件 ,CPU停頓處理垃圾);
4. 篩選回收(stop the world事件 根據使用者期望的GC停頓時間回收)(注意:CMS 在這一步不需要stop the world), Garbage First的原則,選擇一些記憶體塊進行回收;
- 我們會發現以上的四個步驟, 第四步是與CMS不同的, CMS是不STW的, G1的第四步是要STW的, 可以解決CMS 的浮動垃圾問題, 而且時間暫停會靠近設定的暫停值, 不回耽誤很長時間.
- 可預測的停頓 相比於CMS 我們可以預測出停頓的時間
- G1 收集器的特性需要分多個小塊記憶體 所以一般來說 需要的整體的JVM記憶體 也是大的