CMS(Concurrent Mark-Sweep)是以犧牲吞吐量爲代價來得到最短回收停頓時間的垃圾回收器。對於要求服務器響應速度的應用上,這種垃圾回收器很是適合。在啓動JVM參數加上-XX:+UseConcMarkSweepGC ,這個參數表示對於老年代的回收採用CMS。CMS採用的基礎算法是:標記—清除。算法
初始標記(STW initial mark)服務器
併發標記(Concurrent marking)數據結構
併發預清理(Concurrent precleaning)併發
從新標記(STW remark)spa
併發清理(Concurrent sweeping)線程
併發重置(Concurrent reset)指針
初始標記 :在這個階段,須要虛擬機停頓正在執行的任務,官方的叫法STW(Stop The Word)。這個過程從垃圾回收的"根對象"開始,只掃描到可以和"根對象"直接關聯的對象,並做標記。因此這個過程雖然暫停了整個JVM,可是很快就完成了。orm
併發標記 :這個階段緊隨初始標記階段,在初始標記的基礎上繼續向下追溯標記。併發標記階段,應用程序的線程和併發標記的線程併發執行,因此用戶不會感覺到停頓。對象
併發預清理 :併發預清理階段仍然是併發的。在這個階段,虛擬機查找在執行併發標記階段新進入老年代的對象(可能會有一些對象重新生代晉升到老年代, 或者有一些對象被分配到老年代)。經過從新掃描,減小下一個階段"從新標記"的工做,由於下一個階段會Stop The World。圖片
從新標記 :這個階段會暫停虛擬機,收集器線程掃描在CMS堆中剩餘的對象。掃描從"跟對象"開始向下追溯,並處理對象關聯。
併發清理 :清理垃圾對象,這個階段收集器線程和應用程序線程併發執行。
併發重置 :這個階段,重置CMS收集器的數據結構,等待下一次垃圾回收。
CSM執行過程:
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回收器減小了回收的停頓時間,可是下降了堆空間的利用率。
若是你的應用程序對停頓比較敏感,而且在應用程序運行的時候能夠提供更大的內存和更多的CPU(也就是硬件牛逼),那麼使用CMS來收集會給你帶來好處。還有,若是在JVM中,有相對較多存活時間較長的對象(老年代比較大)會更適合使用CMS。