## **概述**
JVM總共有7種垃圾收集器,分別使用不用的回收策略算法用于處理新生代和老年代的數據。
* **新生代收集器**:Serial、ParNew、Parallel Scavenge
* **老年代收集器**:CMS、Serial Old、Parallel Old
* **整堆收集器**: G1
## **相關概念**
* **并行收集**:指多條垃圾收集線程并行工作,但此時用戶線程仍處于等待狀態。
* **并發收集**:指用戶線程與垃圾收集線程同時工作(不一定是并行的可能會交替執行)。用戶程序在繼續運行,而垃圾收集程序運行在另一個CPU上。
* **吞吐量**:即CPU用于運行用戶代碼的時間與CPU總消耗時間的比值(吞吐量 = 運行用戶代碼時間 / ( 運行用戶代碼時間 + 垃圾收集時間 ))。例如:虛擬機共運行100分鐘,垃圾收集器花掉1分鐘,那么吞吐量就是99%
## **一. Serial收集器**
Serial收集器是最基本的、發展歷史最悠久的收集器。
**特點:** 單線程、簡單高效(與其他收集器的單線程相比),對于限定單個CPU的環境來說,Serial收集器由于沒有線程交互的開銷,專心做垃圾收集自然可以獲得最高的單線程手機效率。收集器進行垃圾回收時,必須暫停其他所有的工作線程,直到它結束(Stop The World)。
## **二. Serial Old收集器**
Serial?Old是Serial收集器的老年代版本。
## **三. ParNew收集器**
ParNew收集器是Serial收集器的多線程版本。同樣用于新生代,采用復制算法。
**特點**:多線程、ParNew收集器默認開啟的收集線程數與CPU的數量相同,在CPU非常多的環境中,可以使用-XX:ParallelGCThreads參數來限制垃圾收集的線程數。和Serial收集器一樣存在Stop The World問題
## **四. Parallel Scavenge收集器**
吞吐量優先收集器
**特點**: 屬于新生代收集器也是采用復制算法的收集器,又是并行的多線程收集器(與ParNew收集器類似)。該收集器的目標是達到一個可控制的吞吐量。可使用GC自適應調節策略(與ParNew收集器最重要的一個區別)
**GC自適應調節策略**:Parallel Scavenge收集器可設置-XX:+UseAdptiveSizePolicy參數。當開關打開時不需要手動指定新生代的大小(-Xmn)、Eden與Survivor區的比例(-XX:SurvivorRation)、晉升老年代的對象年齡(-XX:PretenureSizeThreshold)等,虛擬機會根據系統的運行狀況收集性能監控信息,動態設置這些參數以提供最優的停頓時間和最高的吞吐量,這種調節方式稱為GC的自適應調節策略。
Parallel Scavenge收集器使用兩個參數控制吞吐量:
* XX:MaxGCPauseMillis 控制最大的垃圾收集停頓時間
* XX:GCRatio 直接設置吞吐量的大小。
## **五. Parallel?Old?收集器**
是Parallel Scavenge收集器的老年代版本。采用標記-壓縮算法。
## **六. CMS收集器**
一種以獲取最短回收停頓時間為目標的收集器。基于標記-清除算法實現。并發收集、低停頓。
**應用場景**:適用于注重服務的響應速度,希望系統停頓時間最短,給用戶帶來更好的體驗等場景下。如web程序、b/s服務。
**CMS收集器的運行過程分為下列4步:**
1. **初始標記**:標記GC Roots能直接關聯到的對象。速度很快但是仍存在Stop?The?World問題。(產生較短停頓)
2. **并發標記**:進行GC?Roots?Tracing?的過程,并發執行找出存活對象且用戶線程。
3. **重新標記**:為了修正并發標記期間因用戶程序繼續運行而導致標記產生變動的那一部分對象的標記記錄。仍然存在Stop?The?World問題。(產生較短停頓)
4. **并發清除**:并發執行對標記的對象進行清除回收。
**優缺點:** 由于整個過程中耗時最長的并發標記和并發清除過程中,收集器線程都可以與用戶線程一起工作,所以響應時間快,但是并發同時會占用CPU資源會降低吞吐量,標記清除算法會導致內存碎片化。
## **七. G1收集器**
在G1中,堆被劃分成 許多個連續的區域(region)。采用G1算法進行回收,吸收了CMS收集器特點。一款面向服務端應用的垃圾收集器。
**特點:**
* **并行:** G1能充分利用多CPU、多核環境下的硬件優勢,使用多個CPU來縮短Stop-The-World停頓時間
* **并發:** G1收集器可以通過并發方式和用戶線程同時執行,無需暫停用戶線程.
* **分代算法:** G1能夠獨自管理整個Java堆,其它收集器需配合使用才行
* **可預測停頓時間:** 可配置在N毫秒內最多只占用M毫秒的時間進行垃圾回收
**G1收集器大致可分為如下步驟:**
1. **初始標記**:僅標記GC Roots能直接到的對象,并且修改TAMS的值,讓下一階段用戶程序并發運行時,能在正確可用的Region中創建新對象。(產生較短停頓)
2. **并發標記**:從GC Roots開始對堆中對象進行可達性分析,找出存活對象
3. **最終標記**:為了修正在并發標記期間因用戶程序執行而導致標記產生變化的那一部分標記記錄。(產生較短停頓)
4. **篩選回收**:對各個Region的回收價值和成本進行排序,根據用戶所期望的GC停頓時間來制定回收計劃。
## **流行組合**
* **Serial**:數據量小的小型應用
* **ParNew + CMS**:對相應速度有要求的中大型應用
* **ParallelYoung + ParallelOld**:對吞吐量有要求的中大型應用
* **G1GC**:可分配較大堆空間的中大型應用