1. 程式人生 > >CMS垃圾回收過程

CMS垃圾回收過程

1.總體介紹:

CMS(Concurrent Mark-Sweep)是以犧牲吞吐量為代價來獲得最短回收停頓時間的垃圾回收器。對於要求伺服器響應速度的應用上,這種垃圾回收器非常適合。在啟動JVM引數加上-XX:+UseConcMarkSweepGC ,這個引數表示對於老年代的回收採用CMS。CMS採用的基礎演算法是:標記—清除。

2.CMS過程:

  • 初始標記(STW initial mark)
  • 併發標記(Concurrent marking)
  • 併發預清理(Concurrent precleaning)
  • 重新標記(STW remark)
  • 併發清理(Concurrent sweeping)
  • 併發重置(Concurrent reset)

初始標記 :在這個階段,需要虛擬機器停頓正在執行的任務,官方的叫法STW(Stop The Word)。這個過程從垃圾回收的"根物件"開始,只掃描到能夠和"根物件"直接關聯的物件,並作標記。所以這個過程雖然暫停了整個JVM,但是很快就完成了。

併發標記 :這個階段緊隨初始標記階段,在初始標記的基礎上繼續向下追溯標記。併發標記階段,應用程式的執行緒和併發標記的執行緒併發執行,所以使用者不會感受到停頓。

併發預清理 :併發預清理階段仍然是併發的。在這個階段,虛擬機器查詢在執行併發標記階段新進入老年代的物件(可能會有一些物件從新生代晉升到老年代, 或者有一些物件被分配到老年代)。通過重新掃描,減少下一個階段"重新標記"的工作,因為下一個階段會Stop The World。

重新標記 :這個階段會暫停虛擬機器,收集器執行緒掃描在CMS堆中剩餘的物件。掃描從"跟物件"開始向下追溯,並處理物件關聯。

併發清理 :清理垃圾物件,這個階段收集器執行緒和應用程式執行緒併發執行。

併發重置 :這個階段,重置CMS收集器的資料結構,等待下一次垃圾回收。

CSM執行過程: 

3.CMS缺點

  • CMS回收器採用的基礎演算法是Mark-Sweep。所有CMS不會整理、壓縮堆空間。這樣就會有一個問題:經過CMS收集的堆會產生空間碎片。 CMS不對堆空間整理壓縮節約了垃圾回收的停頓時間,但也帶來的堆空間的浪費。為了解決堆空間浪費問題,CMS回收器不再採用簡單的指標指向一塊可用堆空 間來為下次物件分配使用。而是把一些未分配的空間彙總成一個列表,當JVM分配物件空間的時候,會搜尋這個列表找到足夠大的空間來hold住這個物件。
  • 需要更多的CPU資源。從上面的圖可以看到,為了讓應用程式不停頓,CMS執行緒和應用程式執行緒併發執行,這樣就需要有更多的CPU,單純靠執行緒切 換是不靠譜的。並且,重新標記階段,為空保證STW快速完成,也要用到更多的甚至所有的CPU資源。當然,多核多CPU也是未來的趨勢!
  • CMS的另一個缺點是它需要更大的堆空間。因為CMS標記階段應用程式的執行緒還是在執行的,那麼就會有堆空間繼續分配的情況,為了保證在CMS回 收完堆之前還有空間分配給正在執行的應用程式,必須預留一部分空間。也就是說,CMS不會在老年代滿的時候才開始收集。相反,它會嘗試更早的開始收集,已 避免上面提到的情況:在回收完成之前,堆沒有足夠空間分配!預設當老年代使用68%的時候,CMS就開始行動了。 – XX:CMSInitiatingOccupancyFraction =n 來設定這個閥值。

總得來說,CMS回收器減少了回收的停頓時間,但是降低了堆空間的利用率。

4.啥時候用CMS

如果你的應用程式對停頓比較敏感,並且在應用程式執行的時候可以提供更大的記憶體和更多的CPU(也就是硬體牛逼),那麼使用CMS來收集會給你帶來好處。還有,如果在JVM中,有相對較多存活時間較長的物件(老年代比較大)會更適合使用CMS。