JVM之G1和CMS
CMS(Concurrent Mark Sweep) 收集器
CMS 收集器是獲取最短回收停頓時間為目標的收集器。適用於 B/S 系統的服務端。從名字上可以看出來是使用的標記清除演算法。整個清除過程如下:
-
初始標記(CMS initial mark)
- 併發標記(CMS concurrent mark)
- 重新標記(CMS remark)
- 併發清除(CMS concurrent sweep)
其中初始標記和重新標記依然會停止所有的使用者執行緒。
初始標記僅僅是標記一下 GC Roots 能直接關聯到的物件,速度很快。
併發標記階段就是進行 GC Roots Tracing 的過程。
重新標記是為了修正併發標記期間,因使用者程式繼續執行而導致標記產生變動的那一部分物件的標記記錄,這個階段的停頓時間一般比初始標記階段長。
整個 GC 過程當中消耗時間最長的是併發標記和併發清除過程,但是這兩個階段的垃圾回收執行緒可以與使用者執行緒一起併發執行,總體上說,CMS 收集器的記憶體回收過程是與使用者執行緒一起併發執行的。
CMS缺點: - CMS 對 CPU 資源敏感,在併發階段雖然不會停止使用者執行緒,但是會佔用一部分執行緒來進行垃圾回收,總吞吐量會降低。
- CMS 預設啟動的執行緒是(CPU數量+3)/4,當 CPU 大於4個以上佔用資源不超過 25% 的 CPU 資源,但是小於 4 個 CPU 時候 CMS 收集器對使用者程式的影響就比較大。
- CMS 無法回收浮動垃圾。CMS 在併發清理階段還可以執行使用者執行緒,這時候還會產生新的垃圾,而這部分垃圾 CMS 無法在本次回收掉,這部分就是浮動垃圾。因此 CMS 不能像其他的收集器等到年老代幾乎全部滿了再進行回收,需要預留一部分空間提供併發收集時候的使用者執行緒使用。預設設定下,CMS 收集器在年老代使用了 68% 的空間後就會被啟用,可以通過 -XX:CMSInitiatingOccupancyFraction 引數來設定這個屬性。如果 CMS 在執行時候預留的記憶體無法滿足程式需要,就會出現一次“Concurrent Mode Failure”失敗,這時候虛擬機器臨時啟用 Serial Old 收集器重新來進行老年代的垃圾收集。
- CMS 是基於標記整理演算法,在清理的過程中會有大量的空間碎片。空間碎片過多後給打物件分配空間會有很多麻煩。CMS 提供了一個引數 -XX:+UseCMSCompactAtFullCollection 用來在 Full GC 完成後附加一個碎片整理過程,碎片整理無法併發會導致停頓時間變長。當然還提供了一個引數 -XX:CMSFullGCsBeforeCompaction,這個引數設定在執行多少次不壓縮的 Full GC 後,跟著來一次帶壓縮的。
1、CMS收集器
CMS收集器是一種以獲取最短回收停頓時間為目標的收集器。基於“標記-清除”演算法實現,它的運作過程如下:
1)初始標記
2)併發標記
3)重新標記
4)併發清除
初始標記、從新標記這兩個步驟仍然需要“stop the world”,初始標記僅僅只是標記一下GC Roots能直接關聯到的物件,熟讀很快,併發標記階段就是進行GC Roots Tracing,而重新標記階段則是為了修正併發標記期間因使用者程式繼續運作而導致標記產生表動的那一部分物件的標記記錄,這個階段的停頓時間一般會比初始標記階段稍長點,但遠比並發標記的時間短。
CMS是一款優秀的收集器,主要優點:併發收集、低停頓。
缺點:
1)CMS收集器對CPU資源非常敏感。在併發階段,它雖然不會導致使用者執行緒停頓,但是會因為佔用了一部分執行緒而導致應用程式變慢,總吞吐量會降低。
2)CMS收集器無法處理浮動垃圾,可能會出現“Concurrent Mode Failure(併發模式故障)”失敗而導致Full GC產生。
浮動垃圾:由於CMS併發清理階段使用者執行緒還在執行著,伴隨著程式執行自然就會有新的垃圾不斷產生,這部分垃圾出現的標記過程之後,CMS無法在當次收集中處理掉它們,只好留待下一次GC中再清理。這些垃圾就是“浮動垃圾”。
3)CMS是一款“標記--清除”演算法實現的收集器,容易出現大量空間碎片。當空間碎片過多,將會給大物件分配帶來很大的麻煩,往往會出現老年代還有很大空間剩餘,但是無法找到足夠大的連續空間來分配當前物件,不得不提前觸發一次Full GC。
2、G1收集器
G1是一款面向服務端應用的垃圾收集器。G1具備如下特點:
1、並行於併發:G1能充分利用CPU、多核環境下的硬體優勢,使用多個CPU(CPU或者CPU核心)來縮短stop-The-World停頓時間。部分其他收集器原本需要停頓Java執行緒執行的GC動作,G1收集器仍然可以通過併發的方式讓java程式繼續執行。
2、分代收集:雖然G1可以不需要其他收集器配合就能獨立管理整個GC堆,但是還是保留了分代的概念。它能夠採用不同的方式去處理新建立的物件和已經存活了一段時間,熬過多次GC的舊物件以獲取更好的收集效果。
3、空間整合:與CMS的“標記--清理”演算法不同,G1從整體來看是基於“標記整理”演算法實現的收集器;從區域性上來看是基於“複製”演算法實現的。
4、可預測的停頓:這是G1相對於CMS的另一個大優勢,降低停頓時間是G1和CMS共同的關注點,但G1除了追求低停頓外,還能建立可預測的停頓時間模型,能讓使用者明確指定在一個長度為M毫秒的時間片段內,
5、G1運作步驟:
1、初始標記;2、併發標記;3、最終標記;4、篩選回收
上面幾個步驟的運作過程和CMS有很多相似之處。初始標記階段僅僅只是標記一下GC Roots能直接關聯到的物件,並且修改TAMS的值,讓下一個階段使用者程式併發執行時,能在正確可用的Region中建立新物件,這一階段需要停頓執行緒,但是耗時很短,併發標記階段是從GC Root開始對堆中物件進行可達性分析,找出存活的物件,這階段時耗時較長,但可與使用者程式併發執行。而最終標記階段則是為了修正在併發標記期間因使用者程式繼續運作而導致標記產生變動的那一部分標記記錄,虛擬機器將這段時間物件變化記錄線上程Remenbered Set Logs裡面,最終標記階段需要把Remembered Set Logs的資料合併到Remembered Set Logs裡面,最終標記階段需要把Remembered Set Logs的資料合併到Remembered Set中,這一階段需要停頓執行緒,但是可並行執行。最後在篩選回收階段首先對各個Region的回收價值和成本進行排序,根據使用者所期望的GC停頓時間來制定回收計劃。
- -XX:+UseParallelOldGC
- -XX:+UseConcMarkSweep