JVM(HotSpot)7種垃圾收集器


JVM(HotSpot)7種垃圾收集器

7種垃圾收集器作用於不同的分代,如果兩個收集器之間存在連續,就說明他們可以搭配使用。

從JDK1.3到現在,從Serial收集器-》Parallel收集器-》CMS-》G1,用戶線程停頓時間不斷縮短,但仍然無法完全消除。

 

1、Serial收集器(串行收集器)

   

  Serial收集器是最基本、發展歷史最悠久的收集器,曾是(JDK1.3.1之前)虛擬機新生代收集的唯一選擇。

  Serial收集器是一個單線程的收集器。“單線程”的意義不僅僅是它只會使用一個CPU或一條收集器線程去完成垃圾收集工作,更重要的是它在垃圾收集的時候,必須暫停其他所有工作的線程,直到它收集結束。

  Serial收集器是HotSpot虛擬機運行在Client模式下的默認新生代收集器。

  Serial收集器具有簡單而高效,由於沒有線程交互的開銷,可以獲得最高的單線程收集效率(在單個CPU環境中)。

  "-XX:+UseSerialGC":添加該參數來顯式的使用Serial垃圾收集器。

 

2、ParNew收集器

  ParNew收集器是Serial收集器的多線程版本,除了使用多條線程進行垃圾收集之外,其余行為包括Serial收集器可用的所有控制參數、收集算法、Stop The Word、對象分配規則、回收策略等都與Serial收集器一樣。

  ParNew收集器是許多運行在Server模式下的虛擬機首選的新生代收集器,其中一個原因是,除了Serial收集器之外,目前只有ParNew收集器能與CMS收集器配合工作。 

  "-XX:+UseConcMarkSweepGC":指定使用CMS后,會默認使用ParNew作為新生代收集器。

       "-XX:+UseParNewGC":強制指定使用ParNew。   

       "-XX:ParallelGCThreads":指定垃圾收集的線程數量,ParNew默認開啟的收集線程與CPU的數量相同。

  並行(Parallel):指多條垃圾收集線程並行工作,但此時用戶線程仍然處於等待狀態。

  並發(Concurrent):指用戶線程與垃圾收集線程同時執行(但不一定是並行,可能是交替執行),用戶線程繼續工作,而垃圾收集程序運行在另一個CPU上。

 

3、Parallel Scavenge收集器

  Parallel Scavenge收集器是一個新生代收集器,使用復制算法,且是並行的多線程收集器。

  Parallel Scavenge收集器關注點是達到一個可控制的吞吐量(吞吐量 = 運行用戶代碼時間 / (運行用戶代碼時間 + 垃圾收集時間)),而其他收集器關注點在盡可能的縮短垃圾收集時用戶線程的停頓時間。

  Parallel Scavenge收集器提供了兩個參數來用於精確控制吞吐量,一是控制最大垃圾收集停頓時間的 -XX:MaxGCPauseMillis參數,二是控制吞吐量大小的 -XX:GCTimeRatio參數;

  “ -XX:MaxGCPauseMillis” 參數允許的值是一個大於0的毫秒數,收集器將盡可能的保證內存垃圾回收花費的時間不超過設定的值(但是,並不是越小越好,GC停頓時間縮短是以犧牲吞吐量和新生代空間來換取的,如果設置的值太小,將會導致頻繁GC,這樣雖然GC停頓時間下來了,但是吞吐量也下來了)。

  “ -XX:GCTimeRatio”參數的值是一個大於0且小於100的整數,也就是垃圾收集時間占總時間的比率,默認值是99,就是允許最大1%(即1/(1+99))的垃圾收集時間。

  “-XX:UseAdaptiveSizePolicy”參數是一個開發,如果這個參數打開之后,虛擬機會根據當前系統運行情況收集監控信息,動態調整新生代的比例、老年大大小等細節參數,以提供最合適的停頓時間或最大的吞吐量,這種調節方式稱為GC自適應的調節策略。

 

4、Serial Old收集器

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

  Serial Old收集器主要用於Client模式下的虛擬機使用。

  Server模式下的兩大用途:一、在JDK1.5及之前的版本與Parallel Scavenge收集器搭配使用;二、作為CMS收集器的后備方案,在並發收集發生Conturrent Mode Failure時使用。

 

5、Paraller Old收集器

  Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多線程和“標記-整理”算法。

  在JDK1.6中才出現。

 

6、CMS(Conturrent Mark Sweep)收集器

  

  CMS收集器是一種以獲取最短回收停頓時間為目標的收集器。

  目前很大一部分的Java應用集中在互聯網或者B/S系統的服務端上。

  CMS收集器是基於“標記-清除”算法實現,它的整個運行過程可以分為:初始登記(標記一下GC Roots能直接關聯到的對象,這個過程速度很快)、並發標記(進行GCRoots Tracing的過程)、重新標記(修正並發標記期間因用戶線程繼續運作而導致標記產生變動的那一部分對象的標記記錄,速度稍慢)、並發清除(清除死亡的對象)4個步驟;其中,初始標記和重新標記仍然需要“Stop The World”。

  CMS收集器運行的整個過程中,最耗費時間的並發標記和並發清楚過程收集器線程和用戶線程是一起工作的,所以總體來說,CMS收集器的內存回收過程是與用戶線程一起並發執行的。

  優點:並發收集、低停頓。

  缺點:

    一:CMS收集器對CPU資源非常敏感。雖然在兩個並發階段不會導致用戶線程停頓,但是會因為占用了一部分線程而導致應用程序變慢,總吞吐量下降。CMS默認啟動的回收線程數是(CPU數量+3)/4。

    二:CMS收集器無法處理浮動垃圾,可能出現“Conturrent Mode Failure”失敗而導致另一次Full GC產生。由於CMS並發清除階段用戶線程還在運行,伴隨着程序還在產生新的垃圾,這一部分垃圾出現在標記之后,CMS無法在當次收集中處理掉它們,只能留到下次再清理,這一部分垃圾稱為“浮動垃圾”。也正是由於在垃圾收集階段用戶線程還在運行,那么也就需要預留有足夠的內存空間給用戶線程使用,因此CMS收集器不能像其他收集器那樣等待老年代填滿之后再進行收集,需要預留一部分空間給並發收集時用戶程序使用。可以通過“-XX:CMSInitiatingOccupancyFraction”參數設置老年代內存使用達到多少時啟動收集。

    三:由於CMS收集器是一個基於“標記-清除”算法的收集器,那么意味着收集結束會產生大量碎片,有時候往往還有很多內存未使用,可是沒有一塊連續的空間來分配一個對象,導致不得不提前觸發一次Full GC。CMS收集器提供了一個“-XX:UseCMSCompactAtFullCollection”參數(默認是開啟的)用於在CMS收集器頂不住要FullGC時開啟內存碎片整理(內存碎片整理意味着無法並發執行不得不停頓用戶線程)。參數“-XX:CMSFullGCsBeforeCompaction”來設置執行多少次不壓縮的Full GC后,跟着來一次帶壓縮的(默認值是0,意味着每次進入Full GC時都進行碎片整理)。

  

7、G1(Garbage-First)收集器

  

  G1收集器是當今收集器技術發展的最前沿成果之一;

  相比其它收集器,具有如下特點:

    1、並行與並發:G1能夠重發利用多CPU、多核環境下的優勢,使用多個CPU來縮短Stop-The-World停頓時間。

    2、分代收集:與其他收集器一樣,分代概念在G1中依然存在。

    3、空間整合:與CMS的“標記-清理”算法不同,G1從整體來看是基於“標記-整理”來實現的收集器,從局部(兩個Region之間)上來看是基於“復制”算法實現的,這兩種算法都意味着G1運作期間不會產生內存空間碎片,收集后能夠提供整體的可用內存。

    4、可預測停頓:G1除了追求低停頓之外,還能建立可預測的停頓時間模型,能讓使用者明確指定在一個長度為M毫秒的時間片段內,消耗在垃圾收集上的時間不得超過N毫秒。

  使用G1收集器時,Java堆的內存布局與其他收集器有很大的區別,它將整個Java堆划分為多個大小相等的獨立區域(Region),雖然還保留着新生代和老年代的概念,但新生代和老年代不再是物理隔離的了,他們都是一部分Region(不需要連續)的集合。

  G1收集器之所以能夠建立可預測的停頓時間模型,是因為它可以有計划地避免在整個Java對中進行全區域的垃圾收集。G1跟蹤各個Region里面垃圾堆積的價值大小(回收所獲得的空間大小以及回收所需要時間的經驗值),在后台維護一個優先列表,每次根據允許的收集時間,優先回收價值最大的Region(這也是Garbage-First名稱的由來)。

  G1收集器的運作大致可分為:

    1、初始標記:需要停頓,耗時短;

    2、並發標記:

    3、最終標記:需要停頓,可並發執行;

    4、篩選標記:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM