垃圾收集器--CMS垃圾收集器(響應時間優先)

垃圾收集器–CMS垃圾收集器(老年代)

CMS是針對於響應時間優先的垃圾收集器

老年代的CMS一般搭配兩個另外兩個垃圾收集器:
1、ParNewGC (新生代)
2、SerialOld(老年代出現異常時,CMS退化爲SerialOld)

一、ParNewGC (新生代垃圾收集器,並行GC)

ParNew收集器其實就是Serial收集器的多線程版本,除了了使用多條線程進行垃圾收集之外,其餘行爲包括Serial收集器可用的所有控制參數、收集算法、Stop The World、對象分配規則、回收策略等都與 Serial收集器完全一樣,在實現上,這兩種收集器也共用了相當多的代碼。

特性 :

Serial收集器器的多線程版本
多線程
複製算法
Stop The World(STW)

應用場景 :

ParNew收集器是許多運行在Server模式下的虛擬機中首選的新生代收集器,
搭配CMS收集器,在用戶體驗優先的程序中使用:ParNew是運行在Server模式下的虛擬機中首選的新生代收集器,其中有一個與性能無關但很重要的原因是,除了Serial收集器外,目前只有它能與CMS收集器配合工作

優勢

相比單CPU環境,隨着可以使用的CPU的數量的增加,它對於GC時系統資源的有效利用還是很有好處的
提高了cpu的利用率。

對比分析:

與Serial收集器對比:
ParNew收集器在單CPU的環境中絕對不會有比Serial收集器更更好的效果,甚至由於存在線程交互的開銷,該收集器在通過多線程技術實現的兩個CPU的環境中都不能百分之百地保證可以超越Serial收集 器。
然而,隨着可以使用的CPU的數量量的增加,它對於GC時系統資源的有效利用還是很有好處的。

二、CMS垃圾收集器(老年代)

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間爲目標的收集器。目前很大一部分的Java應用集中在互聯網站或者B/S系統的服務端上,這類應用尤其重視服務的響應速度,希望系統停頓時間最短,以給用戶帶來較好的體驗。CMS收集器就非常符合這類應用的需求。

CMS收集器是基於「標記—清除」算法實現的,整個過程分爲4個步驟:

在這裏插入圖片描述
1、初始標記(CMS initial mark) 初始標記僅只是標記一下GC Roots能直接關聯到的對象,速度很快,需要「Stop The World」。
2、併發標記(CMS concurrent mark) 併發標記階段就是進行GC Roots Tracing的過程
3、重新標記重新標記階段是爲了修正併發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間一般會比初始標記階段稍長一些但遠比並發標記的時間短,仍然需要「Stop The World」。
4、併發清除(CMS concurrent sweep) 併發清除階段會清除對象。

注意:由於整個過程中耗時最長的併發標記和併發清除過程收集器線程都可以與用戶線程一起工作,所
以,從總體上來說,CMS收集器的內存回收過程是與用戶線程一起併發執行的。

應用場景

目前很大一部分的Java應用集中在互聯網站或者B/S系統的服務端上,這類應用尤其重視服務的響應速度,希望系統停頓時間最短,以給用戶帶來較好的體驗。CMS收集器就非常符合這類應用的需求。

優點

併發收集、低停頓
「標記-清除」算法

缺點

  1. CMS會搶佔CPU資源。併發標記階段雖然不會導致用戶線程暫停,但卻需要CPU分出精力去執行多條
    垃圾收集線程,從而使得用戶線程的執行速度下降

  2. CMS無法處理浮動垃圾(Floating Garbage),可能會出現「Concurrent Mode Failure」而導致另
    一次Full GC:
    併發清理的過程中,由於用戶線程還在執行,因此就會繼續產生對象和垃圾,這些新的垃圾沒有被標記,CMS只能在下一次收集中處理它們。這也導致了CMS不能在老年代幾乎完全被填滿了再去進行收集,必須預留一部分空間提供給併發收集時程序運作使用。在JDK1.5默認設置下,老年代使用了68%(JDK1.6是92%)的空間後CMS的垃圾收集就會被激活,其實這是一個比較保守的設置,只要應用中老年代增長不是很快,可以適當地調高參數-XX:CMSInitialingOccupancyFraction來提高觸發百分比,降低迴收的頻率來獲得更好的性能。如果CMS在收集期間,內存無法滿足程序的需要,就會出現「Concurrent Mode Failure」,這時JVM將臨時調用單線程的Serial Old收集器來重新進行老年代的垃圾收集,這樣的話,CMS原本降低停頓時間的目的不僅沒完成,和直接使用Serial Old收集器相比,還增加了前面幾個階段的停頓時間

  3. CMS的「標記-清除」算法,會導致大量空間碎片的產生
    碎片的積累會給分配大對象帶來麻煩,往往會出現明明老年代還有很多空間剩餘,但是卻無法找到連續的空間分配對象的情況,這時候就不得不觸發一次Full GC。
    爲了解決這個問題。CMS提供了一個-XX:+UseCMSCompactAtFullCollection的開關參數(默認是開啓的)用於在CMS收集器進行Full GC時對內存碎片進行合併整理,整理的過程是需要暫停用戶線程的,這樣碎片雖然沒有了,但停頓時間又變長了。 CMS的設計初衷可是降低停頓,於是又提供了一個參數-XX:CMSFullGCsBeforeCompaction,用於設置執行多少次不壓縮碎片的Full GC後,跟着來一次帶壓縮的Full GC(默認值爲0,即每次都會)