由於新生代和老年代採用回收算法的不一樣,垃圾收集器相應地也分爲新生代收集器和老年代收集器
新生代收集器主要有Serial收集器、ParNew收集器和Parallel Scavenge收集器
老年代收集器主要有Serial Old收集器、Parallel Old收集器和CMS收集器
固然還包括了一款全新的、新生代老年代通用的G1收集器
各款收集器的搭配使用以下圖所示,其中有連線的表明收集器能夠搭配使用,沒有連線的收集器表示不能搭配使用算法
其中顯示爲?號的收集器叫作G1收集器,是目前最新的收集器。多線程
參數配置 | 新生代和老年代垃圾收集器組合 |
-XX:+UseSerialGC | Serial + Serial Old |
-XX:+UseParNewGC | ParNew + Serial Old |
-XX:+UseParallelGC | Parallel Scavenge + Serial Old |
-XX:+UseConcMarkSweepGC | ParNew + CMS/Serial Old(備選) |
-XX:+UseParallelOldGC | Parallel Scavengen + Parallel Old |
Serial收集器做用於新生代,是一個單線程收集器,基於複製算法實現。在進行垃圾回收的時候僅使用單條線程而且在回收的過程當中會掛起全部的用戶線程(Stop The World)。Serial收集器是JVM client模式下默認的新生代收集器。併發
特別注意,Stop-The-World會掛起應用線程,形成應用的停頓。spa
參數控制: -XX:+UseSerialGC線程
ParNew收集器做用於新生代,是一個多線程收集器,基於複製算法實現。相對於Serial收集器而言,在垃圾回收的時候會同時使用多條線程進行回收,可是它跟Serial收集器同樣,在回收過程當中也是會掛起全部的用戶線程,從而形成應用的停頓。日誌
參數控制: -XX:+UseParNewGC對象
Parallel Scavenge收集器一樣做用於新生代,而且也是採用多線程和複製算法來進行垃圾回收。Parallel Scavenge收集器關注的是吞吐量,即便得應用可以充分使用CPU。它與ParNew收集器同樣,在回收過程會掛起全部的用戶線程,形成應用停頓。內存
所謂吞吐量就是CPU用於運行用戶代碼的時間與CPU總消耗時間的比值。即吞吐量 = 運行用戶代碼時間 / (運行用戶代碼時間 + 垃圾收集時間)。若是虛擬機運行了100分鐘,其中垃圾收集花了1分鐘,那麼吞吐量就是99%。ci
參數控制:-XX:+UseParallelGCrem
Serial Old收集器做用於老年代,採用單線程和標記-整理算法來實現垃圾回收。在回收垃圾的時候一樣會掛起全部用戶線程,形成應用的停頓。通常來講,老年代的容量都比新生代要大,因此當發生老年代的垃圾回收時,STW經歷的時間會比新生代所用的時間長得多。該收集器是JVM client模式下默認的老年代收集器。
Serial Old收集器還有一個重要的用途是做爲CMS收集器的後備方案,在併發收集發生Concurrent Mode Failure的時候使用,進行內存碎片的整理。
Parallel Old收集器是Parallel Scavenge收集器的老年代版本,採用多線程和標記-整理算法來實現老年代的垃圾回收。這個收集器主要是爲了配合Parallel Scavenge收集器的使用,即當新生代選擇了Parallel Scavenge收集器的狀況下,老年代能夠選擇Parallel Old收集器。
在JDK1.6之前並無提供Parallel Scavenge收集器,因此在1.6版本之前,Parallel Scavenge收集器只能與Serial Old收集器搭配使用。
參數控制:-XX:+UseParallelOldGC
CMS(Concurrent Mark Sweep)收集器是一款真正實現了併發收集的老年代收集器。CMS收集器以獲取最短回收停頓時間爲目標,採用多線程併發以及標記-清除算法來實現垃圾回收。CMS只在初始化標記和從新標記階段須要掛起用戶線程,形成必定的應用停頓(STW),而其餘階段收集線程均可以與用戶線程併發交替進行,沒必要掛起用戶線程,因此並不會形成應用的停頓。CMS收集器能夠最大程度地減小因垃圾回收而形成應用停頓的時間。
CMS垃圾收集分爲如下幾個階段:
(1) 初始化標記 (inital mark)
這個階段僅僅是標記了GC Roots可以直接關聯到的對象,速度很快,因此基本上感覺不到STW帶來的停頓。
(2) 併發標記 (concurrent mark)
併發標記階段完成的任務是從第一階段收集到的對象引用開始,遍歷全部其餘的對象引用,並標記全部須要回收的對象。這個階段,收集線程與用戶線程併發交替執行,沒必要掛起用戶線程,因此並不會形成應用停頓。
(3) 併發預清除 (concurrent-pre-clean)
併發預清除階段是爲了下一個階段作準備,爲的是儘可能減小應用停頓的時間。
(4) 從新標記 (remark)
這個階段將會修正併發標記期間由於用戶程序繼續運做而致使標記產生變更的那部分對象的標記記錄(有可能對象從新被引用或者新對象能夠被回收)。這個階段的停頓時間比初始標記階段要長一些,可是遠比並發標記的時間短。
(5) 併發清除 (concurrent sweep)
這個階段將真正執行垃圾回收,將那些不被使用的對象內存回收掉。
(6) 併發重置 (concurrent reset)
收集器作一些收尾的工做,以便下一次GC週期能有一個乾淨的狀態。
使用CMS要注意如下兩個關鍵詞:
對於採用CMS進行老年代GC的程序而言,尤爲要注意GC日誌中是否有promotion failed和concurrent mode failure兩種情況,當這兩種情況出現時可能會觸發Full GC。promotion failed是在進行Minor GC時,新生代的survivor區放不下,對象只能放入老年代,而此時老年代也放不下形成的。concurrent mode failure是在執行CMS GC的過程當中同時有對象要放入老年代(知足必定年齡的對象或者大對象),而此時老年代空間不足形成的。
參數控制: -XX:+UseConcMarkSweepGC
- 一般咱們把發生在新生代的垃圾回收稱爲Minor GC,而把發生在老年代的垃圾回收稱爲Major GC,而FullGC是指整個堆內存的垃圾回收,包括對新生代、老年代和持久代的回收。通常狀況下應用程序發生Minor GC的次數要遠遠大於Major GC和Full GC的次數。
- 在講解GC的時候會涉及到並行和併發兩個概念。在這裏,並行指的是多個GC收集線程之間並行進行垃圾回收。而併發指的是多個GC收集線程與全部的用戶線程可以交替執行。
Garbage First(G1)垃圾回收器
空間整合,G1收集器採用標記整理算法,不會產生內存空間碎片。分配大對象時不會由於沒法找到連續空間而提早觸發下一次GC。
可預測停頓,這是G1的另外一大優點,下降停頓時間是G1和CMS的共同關注點,但G1除了追求低停頓外,還能創建可預測的停頓時間模型,能讓使用者明確指定在一個長度爲N毫秒的時間片斷內,消耗在垃圾收集上的時間不得超過N毫秒,這幾乎已是實時Java(RTSJ)的垃圾收集器的特徵了。