HotSpot虛擬機全部的垃圾收集器以下圖:算法
上面有7種收集器,分爲部分,上面爲新生代收集器,下面是老年代收集器。若是兩個收集器之間存在連線,就說明它們能夠搭配使用。多線程
新生代的收集器使用複製算法,
老年代使用併發標記清除(CMS)或標記-整理算法。併發
Java中Stop-The-World機制簡稱STW,是在執行垃圾收集算法時,Java應用程序的其餘全部線程都被掛起(除了垃圾收集幫助器以外)。Java中一種全局暫停現象,全局停頓,全部Java代碼中止,native代碼能夠執行,但不能與JVM交互。spa
序號 | 收集器 | 收集範圍 | 算法 | 執行類型 |
---|---|---|---|---|
1 | Serial | 新生代 | 複製 | 單線程 |
2 | ParNew | 新生代 | 複製 | 多線程並行 |
3 | Parallel | 新生代 | 複製 | 多線程並行 |
4 | Serial Old | 老年代 | 標記整理 | 單線程 |
5 | CMS | 老年代 | 標記清除 | 多線程併發 |
6 | Parallel Old | 老年代 | 標記整理 | 多線程 |
7 | G1 | 所有 | 複製算法,標記-整理 | 多線程 |
解釋:
並行(Parallel):多條垃圾收集線程並行工做,而用戶線程仍處於等待狀態
併發(Concurrent):垃圾收集線程與用戶線程一段時間內同時工做(交替執行)線程
Serial收集器是一個新生代收集器,單線程執行,使用複製算法。它在進行垃圾收集時,必 須暫停其餘全部的工做線程(用戶線程)。是Jvm client模式下默認的新生代收集器。對於限定單個CPU的環境來講,Serial收集器因爲沒有線程交互的開銷,專心作垃圾收集天然能夠得到最高的單 線程收集效率。對象
ParNew收集器其實就是serial收集器的多線程版本,除了使用多條線程進行垃圾收集以外,其他行爲與Serial收集器同樣。blog
Parallel Scavenge收集器也是一個新生代收集器,它也是使用複製算法的收集器,又是並行多線程收集器。parallel Scavenge收集器的目標則是達到一個可控制的吞吐量。吞吐量= 程序運行時間/(程序運行時間 + 垃圾收集時間),虛擬機總共運行了100分鐘。其中垃圾收集花掉1分鐘,那吞吐量就是99%。內存
使用以下2個參數進行控制吞吐量資源
示意圖和ParNew相似(參見圖3-7)。rem
Serial Old是Serial收集器的老年代版本,它一樣使用一個單線程執行收集,使用「標記-整理」算法。主要使用在Client模式下的虛擬機。若是在Server模式下,它主要還有兩大用途:一個是在JDK 1.5及以前的版本中與Parallel Scavenge收集器搭配使用,另一個就是做爲CMS收集器的後備預案。若是CMS收集器出現Concurrent Mode Failure,則Serial Old收集器將做爲後備收集器。
詳見圖3-6 老年的收集
Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和「標記-整理」算法。
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間爲目標的收集器。CMS收集器是基於「標記-清除」算法實現的,整個收集過程大體分爲4個步驟:
其中初始標記、從新標記這兩個步驟任然須要停頓其餘用戶線程。初始標記僅僅只是標記出GC ROOTS能直接關聯到的對象,速度很快,併發標記階段是進行GC ROOTS 根搜索算法階段,會斷定對象是否存活。而從新標記階段則是爲了修正併發標記期間,因用戶程序繼續運行而致使標記產生變更的那一部分對象的標記記錄,這個階段的停頓時間會被初始標記階段稍長,但比並發標記階段要短。
因爲整個過程當中耗時最長的併發標記和併發清除過程當中,收集器線程均可以與用戶線程一塊兒工做,因此總體來講,CMS收集器的內存回收過程是與用戶線程一塊兒併發執行的。
CMS收集器的優勢:併發收集、低停頓,可是CMS還遠遠達不到完美,器主要有三個顯著缺點:
CMS收集器對CPU資源很是敏感。
在併發階段,雖然不會致使用戶線程停頓,可是會佔用CPU資源而致使引用程序變慢,總吞吐量降低。CMS默認啓動的回收線程數是:(CPU數量+3)/4。(建議CPU個數最少4個)。
沒法處理浮動垃圾
在作垃圾回收的過程當中會產生新的垃圾(並行執行),因此須要預留一部分空間給用戶線程使用。
可使用-XX:CMSInitiatingOccupancyFraction(jdk1.6 默認爲92%)參數來設置,預留多少空間開始作GC。若是在垃圾回收的過程當中,剩餘空間不足仍然知足不了用戶線程生成對象所須要的空間,就會出現「Concurrent Mode Failure」失敗,這時候虛擬機將啓動後備預案:臨時啓用Serial Old收集器來從新進行老年代的垃圾收集,這樣停頓時間就很長了。
CMS是基於「標記-清除」算法實現的收集器,使用「標記-清除」算法收集後,會產生大量碎片。
空間碎片太多時,將會給對象分配帶來不少麻煩,好比說大對象,內存空間找不到連續的空間來分配不得不提早觸發一次Full GC。爲了解決這個問題,CMS收集器提供了一個-XX:UseCMSCompactAtFullCollection開關參數,用於在Full GC以後增長一個碎片整理過程,還可經過-XX:CMSFullGCBeforeCompaction參數設置執行多少次不壓縮的Full GC以後,跟着來一次碎片整理過程。
七、G1收集器
G1(Garbage First)垃圾回收器是用在heap memory很大的狀況下,把heap劃分爲不少不少的region塊,而後並行的對其進行垃圾回收。
G1垃圾回收器在清除實例所佔用的內存空間後,還會作內存壓縮。
G1垃圾回收器回收region的時候基本不會STW,而是基於 most garbage優先回收 的策略來對region進行垃圾回收的。
結果以下圖:
一個region有可能屬於Eden,Survivor或者Tenured內存區域。圖中的E表示該region屬於Eden內存區域,S表示屬於Survivor內存區域,T表示屬於Tenured內存區域。圖中空白的表示未使用的內存空間。G1垃圾收集器還增長了一種新的內存區域,叫作Humongous內存區域,如圖中的H塊。這種內存區域主要用於存儲大對象-即大小超過一個region大小的50%的對象。
在G1垃圾收集器中,年輕代的垃圾回收過程使用複製算法。把Eden區和Survivor區的對象複製到新的Survivor區域。
以下圖:
對於年老代上的垃圾收集,G1垃圾收集器也分爲4個階段,基本跟CMS垃圾收集器同樣,但略有不一樣:
Initial Mark階段 - 同CMS垃圾收集器的Initial Mark階段同樣,G1也須要暫停應用程序的執行,它會標記從根對象出發,在根對象的第一層孩子節點中標記全部可達的對象。可是G1的垃圾收集器的Initial Mark階段是跟minor gc一同發生的。也就是說,在G1中,你不用像在CMS那樣,單獨暫停應用程序的執行來運行Initial Mark階段,而是在G1觸發minor gc的時候一併將年老代上的Initial Mark給作了。
Concurrent Mark階段 - 在這個階段G1作的事情跟CMS同樣。但G1同時還多作了一件事情,就是若是在Concurrent Mark階段中,發現哪些Tenured region中對象的存活率很小或者基本沒有對象存活,那麼G1就會在這個階段將其回收掉,而不用等到後面的clean up階段。這也是Garbage First名字的由來。同時,在該階段,G1會計算每一個 region的對象存活率,方便後面的clean up階段使用 。
Remark階段 - 在這個階段G1作的事情跟CMS同樣, 可是採用的算法不一樣,G1採用一種叫作SATB(snapshot-at-the-begining)的算法可以在Remark階段更快的標記可達對象。
Clean up/Copy階段 - 在G1中,沒有CMS中對應的Sweep階段。相反 它有一個Clean up/Copy階段,在這個階段中,G1會挑選出那些對象存活率低的region進行回收,這個階段也是和minor gc一同發生的,以下圖所示: