JVMGC——併發收集器(CMS)

 CMS(Concurrent Mark Sweep)收集器

C :  Concurrent

M :  標記(marking)對象 :GC必須記住哪些對象可達,以便刪除不可達的對象 

S :  清除(sweeping) : 刪除未標記的對象並釋放它們的內存


CMS是一種以最短停頓時間爲目標的收集器,使用CMS並不能達到GC效率最高,但它儘可能降低GC時服務的停頓時間。

使用標記-清除算法(Mark Sweep),在運行時會產生內存碎片

虛擬機提供了參數開啓CMS收集結束後再進行一次內存壓縮。

-XX:+UseConcMarkSweepGC

激活CMS收集器。默認HotSpot JVM使用的是並行收集器

-XX:+UseCMSCompactAtFullCollection  

設置在垃圾收集器後是否需要一次內存碎片整理過程,僅在CMS收集器時有效
-XX:+CMSFullGCBeforeCompaction
設置CMS收集器在進行若干次垃圾收集後再進行一次內存碎片整理過程
通常與UseCMSCompactAtFullCollection參數一起使用

CMS垃圾回收整個過程分爲六個步驟:

1. 初始標記 (CMS initial mark)  會STW(Stop The World)

爲了收集應用程序的對象引用需要暫停應用程序線程

該階段完成後,應用程序線程再次啓動


2. 併發標記 (CMS concurrent mark)

從第一階段收集到的對象引用開始,遍歷所有其他的對象引用


3. 併發預清理(CMS-concurrent-preclean)

改變當運行第二階段時,由應用程序線程產生的對象引用,以更新第二階段的結果


4. 重新標記 (CMS remark)  會STW

由於第三階段是併發的,對象引用可能會發生進一步改變,因此應用程序線程會再一次被暫停以更新這些變化

並且在進行實際的清理之前確保一個正確的對象引用視圖


5. 併發清理 (CMS concurrent sweep)  

所有不再被引用的對象將從堆裏清除掉


6. 併發重置:

收集器做一些收尾的工作,以便下一次GC週期能有一個乾淨的狀態




CMS的兩個挑戰:

1. 堆碎片

CMS收集器默認並沒有任何碎片整理的機制。所以可能會出現這樣的情形:

即使總的堆大小遠沒有耗盡但卻不能分配對象,僅僅是因爲沒有足夠連續的空間完全容納對象

當這種事發生後,JVM會觸發Full GC

 

2. 對象分配率高

獲取對象實例的頻率高於收集器清除堆裏死對象的頻率

併發模式失敗: 老年代沒有足夠的可用空間來容納一個從年輕代提升過來的對象

此時JVM會執行堆碎片整理:觸發Full GC

 

當這些情形之一出現的時候,經常被證實是老年代有大量不必要的對象

一個可行的辦法: 增加年輕代的堆大小(增加Survior區的個數),以防止年輕代生命週期短的對象提前進入老年代。

其他方法: 利用jmap和jhat分析過度的對象分配,找出這些對象,最終減少這些對象的申請。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章