JVM—GC垃圾回收器總結

收集算法(標記-清理、複製、標記-整理、分代收集)是內存回收的方法論,垃圾收集器就是內存回收的具體實現。java

主要有7個gc器,以下圖。gc器算法

1 Serial收集器

1.1 介紹

Serial收集器是單線程的收集器。
單線程:1.不只僅說明它只會使用一個CPU或一條收集線程去完成垃圾收集工做,2.且在垃圾收集時,必須暫停其餘全部的工做線程,直到它收集結束。
Stop the world:是VM在後臺自動發起和自動完成的,在用戶不可見狀況下把用戶正常工做的線程所有停掉。安全

1.2 缺點:

因爲Stop The World,給用戶帶來不良體驗,好比,計算機每運行一段時間就會暫停響應幾分鐘來處理垃圾收集。數據結構

1.3 優勢

1)簡單而高效(與其餘收集器的單線程比);
2)對於限定單個CPU的環境來講,Serial收集器因爲沒有線程交互的開銷,專心作垃圾收集天然能夠得到最高的單線程收集效率。多線程

1.4 應用場景

1)VM運行在Client模式下的默認新生代收集器;
2)在用戶的桌面應用場景中,停頓時間徹底能夠控制在幾十毫秒最多一百多毫秒之內,不頻繁發生,是可接受的併發

1.5 Serial/Serial Old收集器運行示意圖

Serial/Serial Old收集器

2 ParNew收集器

2.1 介紹

ParNew收集器是Serial收集器多線程版本(是GC線程的多線程,並行)。
並行:Parallel指多條垃圾收集線程並行工做,但此時用戶線程仍然處於等待狀態(多個處理器同時處理多條指令);
併發:Concurrent指用戶線程與垃圾收集線程同時執行(但並不必定是並行的,可能交替執行),用戶程序在繼續運行,而垃圾收集程序運行於另外一個CPU上(同一時刻只能有一條指令執行,多個進程指令是交替執行)。性能

2.2 缺點

在單CPU的環境中絕對不會有比Serial收集器更好的效果,甚至存在線程交互的開銷。網站

2.3 優勢

1)除了Serial收集器外,只有ParNew收集器能與CMS收集器配合工做。
2)CMS(Concurrent Mark Sweep)第一次實現讓垃圾收集線程與用戶線程(基本上)同時工做。操作系統

2.4 應用場景

運行在Server模式下的VM首選新生代收集器。線程

2.5 ParNew/Serial Old收集器運行示意圖

ParNew/Serial Old收集器

2.6 參數控制

• 使用-XX:+UseConcMarkSweepGC選項後默認新生代收集器爲ParNew收集器;
• 使用-XX:+UseParNewGC選項強制指定使用ParNew收集器;
• 使用-XX:ParallelGCThreads參數限制垃圾收集的線程數;

3 Parallel Scavenge收集器

3.1 介紹

1)Parallel Scavenge收集器是一個新生代收集器,使用複製算法的收集器,並行的多線程收集器。更關注吞吐量。
2)吞吐量:CPU用於運行用戶代碼的時間與cpu總消耗時間的比值,即
吞吐量計算公式如虛擬機總共運行100分鐘,垃圾收集花費1分鐘,則吞吐量是99%;吞吐量高效率利用CPU時間,儘快完成程序的運算任務,主要適合後臺運算而不須要太多交互的任務。
3)停頓時間:如CMS等收集器關注點儘量縮短垃圾收集時用戶線程的停頓時間,停頓時間越短就越適合須要與用戶交互的程序,良好的響應速度能夠提高用戶體驗(適合交互)

3.2 參數控制

1)用戶精確控制吞吐量
• 使用-XX:MaxGCPauseMillis參數:控制最大垃圾收集停頓時間
• 使用-XX:GCTimeRatio參數:直接設置吞吐量大小
• 使用-XX:+UseAdaptiveSizePolicy開關參數:GC自適應的調節策略
2)MaxGCPauseMillis參數容許的值是一個大於0的毫秒數,收集器儘量保證內存回收時間不超過設定值。
GC停頓時間縮短犧牲吞吐量和新生代空間——若將MaxGCPauseMillis該值調小帶來的問題:系統把新生代調小一些,收集發生更頻繁一些,吞吐量降低。
GCTimeRatio參數值是一個大於0且小於100的整數,即垃圾收集時間佔總時間的比率,至關於吞吐量的倒數。如設置爲19,則最大GC時間佔1/(1+19)=5%,默認值爲99.則最大容許1/(1+99)=1%的垃圾收集時間。
UseAdaptiveSizePolicy開關參數:VM會根據當前系統的運行狀況收集性能監控信息,動態調整這些參數以提供最合適的停頓時間或最大吞吐量。自適應調節策略是Parallel Scavenge收集器與ParNew收集器的重要區別。

3.3 應用場景

主要適合後臺運算而不須要太多交互的任務

4 Serial Old收集器

4.1 介紹

Serial Old收集器是Serial收集器的老年代版本,是一個單線程收集器,使用「標記-整理」算法。

4.2 應用場景

1)主要給Client模式下的VM使用。
2)若在Server模式下用,兩大用途:1.在JDK1.5及以前的版本中與Parallel Scavenge收集器搭配使用;2.做爲CMS收集器備選,並在Concurrent Mode Failure時使用。

4.3 Serial/Serial Old收集器運行示意圖

Serial/Serial Old收集器

5 Parallel Old收集器

5.1 介紹

Parallel Old是Parallel Scavenge收集器的老年代版本,是一個多線程收集器,使用「標記-整理」算法。在JDK1.6開始提供。

5.2 應用場景

注重吞吐量以及CPU資源敏感的場合,優先考慮Parallel Scavenge + Parallel Old收集器。適合吞吐量優先。

5.3 Parallel Scavenge /Parallel Old收集器運行示意圖

Parallel Scavenge /Parallel Old收集器

6 CMS收集器

6.1 介紹

CMS收集器(Concurrent Mark Sweep)是一種以獲取最短回收停頓時間爲目標的收集器,是基於「標記-清除」算法。

6.2 CMS的整個過程有4個步驟

初始標記——併發標記——從新標記——併發清除

初始標記:CMS initial mark僅僅是標記一下GC Roots能直接關聯的對象,速度快;須要stop the world
併發標記:CMS concurrent mark是進行GC Roots Tracing的過程;
從新標記:CMS remark是修正併發標記期間因用戶程序繼續運做而致使標記產生變更的那一部分對象的標記記錄,停頓時間比初始標記長,比並發標記短;須要stop the world
併發清除:CMS concurrent sweep,清除算法會在收集結束時產生大量空間碎片,有可能致使沒有足夠大的連續空間來分配當前對象而觸發一次Full GC。

6.3 缺點

1)CMS收集器對CPU資源很是敏感;
2)CMS收集器沒法處理浮動垃圾,可能出現"Concurrent Mode Failure"失敗(備選用Serial Old)而致使另外一次Full GC的產生;
3)CMS是一款基於「標記-清除」算法的收集器,在收集結束後會產生大量空間碎片。
缺點具體分析
1)對CPU資源敏感:在併發階段會佔用一部分線程而致使應用程序變慢,總吞吐量下降;(解決方法是「增量式併發收集器」,但不提倡使用,i-CMS收集器是與單CPU年代PC機操做系統使用搶佔式模擬多任務機制的思想,在併發標記、清理的時候讓GC線程、用戶線程交替執行,儘可能減小GC線程的獨佔資源的時間)
2)沒法處理浮動垃圾:CMS併發清理階段用戶線程還在運行,會產生新的垃圾,這部分垃圾出如今標記過程以後,CMS沒法在當次收集中處理它們,只好留到下一次GC時再處理。CMS須要預留一部分提供併發收集時的程序運行使用,CMS收集時老年代不能填滿再收集。
3)收集後產生大量空間碎片:「標記-清除」算法的缺點,解決方案是使用-XX:+UseCMSCompactAtFullCollection和-XX:CMSFullGCsBeforeCompaction參數

6.4 優勢

併發收集;低停頓(併發低停頓收集器)

6.5 應用場景

在互聯網站或者B/S系統的服務端上,重視服務的響應速度,但願系統停頓時間最短,給用戶帶來較好的體驗。

6.6 參數控制

  • 使用-XX:CMSInitiatingOccupancyFraction參數:提升觸發老年代CMS垃圾回收的百分比;
  • 使用-XX:+UseCMSCompactAtFullCollection開關參數:默認開啓,用於CMS收集器要進行Full GC時開啓內存碎片合併整理過程,非併發的過程;
  • 使用-XX:CMSFullGCsBeforeCompaction參數:用於設置執行多少次不壓縮的Full GC後,緊接着一次帶壓縮的(默認爲0,表示每次進入Full GC時就進行碎片整理)

6.7 CMS收集器運行時示意圖

CMS收集器工做流程

7 G1收集器

7.1 介紹

G1(Garbage-First)收集器是一款面向服務端應用的垃圾收集器,爲了代替JDK1.5中發佈的CMS收集器。將整個Java堆劃分爲多個大小相等的獨立區域。####(Region),保留新生代和老年代概念,但再也不是物理隔離,是一部分Region的集合(不須要連續)。

7.2 優勢

併發與並行、分代收集、空間整合、可預測的停頓

• 併發與並行:G1能充分利用多CPU、多核環境下的硬件優點,使用多個CPU縮短storp-the-world停頓時間;G1可經過併發的方式使得java程序運行;
• 分代收集:能夠獨立管理整個GC堆,採用不一樣的方式處理新建立的對象和已經存活一段時間、熬過屢次GC的舊對象以獲取更好的收集效果;
• 空間整合:總體上基於「標記-整理」算法,局部(兩個Region之間)基於「複製」算法,G1運行期間不會產生內存空間碎片,收集後能提供規整的可用內存,有利於程序長時間運行,分配大對象時不會由於沒法得到連續內存空間而提早觸發下一次GC;
• 可預測的停頓:相比於CMS的另外一優點,能讓使用者明確指定在一個長度爲M毫秒的時間片斷內,消耗在垃圾收集上的時間不得超過N毫秒。由於能夠有計劃地避免在整個java堆上進行全區域的垃圾收集。G1跟蹤各個Region內垃圾堆積的價值大小(回收所得到的空間大小+回收所需時間的經驗值),在後臺維護一個優先列表,根據容許的收集時間,回收價值最大的Region(Garbage-First的由來)。

7.3 G1將內存「化整爲零」的思路

Region之間的對象引用以及其餘收集器中的新生代與老年代之間的對象引用,VM都是經過Remember Set來避免全堆掃描。G1中每一個Region中都有一個與之對應的Remember Set:
1)VM發現程序對Reference類型的數據進行寫操做時,會產生一個Write Barrier暫時中斷寫操做;
2)檢查Reference引用的對象是否處於不一樣的Region之中;若是是,便經過CardTable把相關引用信息記錄到被引用對象所屬的Region的Remember Set之中;
3)當進行內存回收時,在GC根節點的枚舉範圍中加入Remember Set便可保證不對全堆掃描;

(4)G1收集器運做的步驟:

初始標記——併發標記——最終標記——篩選回收

  • 初始標記:initial marking,標記一下GC Roots能直接關聯的對象,而且修改TAMS(Next Top at Mark Start)的值,讓下一階段用戶程序併發運行時,能在正確可用的Region中建立新對象,須要停頓線程,耗時短;
  • 併發標記:concurrent marking,從GC Root開始對堆中對象進行可達性分析,找出存活的對象,這階段耗時長,但可與用戶程序併發執行;
  • 最終標記:final marking,修正在併發標記期間因用戶程序繼續運做而致使標記產生變更的那一部分標記記錄,對象變化記錄存在線程Remember Set Logs中,而後把這些數據合併到Remember Set中,該階段停頓線程,可是可並行執行;
  • 篩選回收:live data counting and evacuation,對各個Region的回收價值和成本進行排序,根據用戶所指望的GC停頓時間來指定回收計劃。

    (5)G1收集器運行示意圖:

    G1收集器工做流程

    8 安全點

    8.1 介紹

    1)Safepoint:在HotSpot的實現中,使用一組稱爲OopMap的數據結構,在類加載完成的時候,HotSpot把對象帶內什麼偏移量上是什麼類型的數據都計算出來,在JIT編譯過程當中,也會在特定的位置記錄下棧和寄存器中哪些位置是引用,這些特定的位置就是安全點。
    2)程序執行時並不是在全部的地方都能停頓下來開始GC,只有到達安全點時才能暫停。
    3)安全點的選定:標準是「是否具備讓程序長時間執行的特徵」,不能太少以致於讓GC等待時間太長,也不能過於頻繁以致於過度增大運行時的負荷。

8.2 安全點的停頓

如何在GC發生時讓全部線程都「跑」到最近的安全點停頓?兩種方案:搶先式中斷和主動式中斷。

搶先式中斷:不須要線程的執行代碼主動去配合,在GC發生時,首先把全部線程所有中斷,若是發現有線程中斷的地方不在安全點上,就恢復線程,讓它「跑」到安全點上。(如今幾乎不用)
主動式中斷:當GC須要中斷線程的時候,不直接對線程操做,僅僅設置一個標誌,各個線程執行時主動去輪詢這個標誌,發現中斷標誌爲真時就本身中斷掛起。輪詢標誌的地方和安全點是重合的,另外再加上建立對象須要分配內存的地方。

8.3 安全點的做用

1)safepoint保證程序執行時,在不太長的時間內就會遇到可進入的GC的safepoint。
2)若程序不執行,則沒有分配CPU時間,如線程處於Sleep或Blocked狀態,沒法響應JVM的中斷請求,此時須要安全區域解決,在一段代碼片斷中,引用關係不會發生變化,在這個區域中的任意地方開始GC都是安全的。

9 垃圾收集器的參數總結

9.1 GC器的參數

GC參數

9.2 GC器的使用

GC器配合使用

主要參考了《深刻理解Java虛擬機》這本書,這本書是真心好,值得一讀。

相關文章
相關標籤/搜索