【Java】JVM垃圾收集器

概述

垃圾收集算法是垃圾回收的方法論, 垃圾回收器則是垃圾回收的具體實現。

各個廠商差異較大, 這裏只討論常用的HotSpot虛擬機。

在這裏插入圖片描述

HotSpot垃圾收集器可搭配使用的關係圖。

爲了應對不同的場景和需求,需要選擇不同的新生代和年老代垃圾收集器搭配使用。

Serial

串行收集器,採用複製算法, HotSpot運行在Client模式下的默認新生代收集器。

特點:

  • 單線程, 一但進行垃圾收集必須暫停其他所有線程(Stop The World)

  • 單線程垃圾收集簡單高效。

參數 :

-XX:+UseSerialGC  使用Serial作爲新生代收集器

在這裏插入圖片描述

ParNew

並行收集器, 採用複製算法, Serial的多線程版本, Server模式下的首選新生代收集器

特點:

  • 多線程, 多核CPU下對系統資源的利用率較高, 其餘屬性與Serial相同.

  • 除了Serial外唯一能和CMS收集器配合工作的收集器.

參數:

-XX:+UseParNewGC        指定使用ParNew垃圾收集器
-XX:ParallelGCThreads   指定垃圾收集的線程數

在這裏插入圖片描述

Parallel Scavenge

並行多線程新生代收集器, 採用複製算法.

特點:

  • 關注垃圾收集器的吞吐量,
  • 實現吞吐量可控, 高效地利用CPU資源.
  • 無法與CMS收集器配合工作

參數:

-XX: MaxGCPauseMillis      收集器盡力保證收集時間不超過設定值.
-XX: GCTimeRatio   		    值是一個大於0小於100的整數, 即垃圾收集時間佔總時間的比例.
-XX:+UseAdaptiveSizePolicy  開關參數,自動調整定-Xmn、 -XX:SurvivorRatio、-XX:PretenureSizeThreshold等
							參數以提供最合適的停頓時間和吞吐量.GC自適應調節.
-XX:+UseParallelGC          新生代使用Parallel收集器
 -XX:+UseParallelOldGC      老年代使用Parallel old收集器

Serial Old

Serial的老年代版本, 單線程收集器, 採用標記-整理算法, 在Client模式下使用.

特性:

  • 在JDK1.5以及之前的版本中與Parallel Scavenge配合使用
  • 可以作爲CMS的後備預案, 在併發收集發生Concurrent Mode Failure時使用.

在這裏插入圖片描述

Parallel Old

Parallel Scavenge的年老代版本, 多線程上映標記-整理算法, jdk1.6中開始提供.

特性:

  • Parallel Scavenge+Serial Old地位尷尬. Parallel Scavenge + Parallel Old可以再之中吞吐量和CPU資源敏感的場合搭配使用.

在這裏插入圖片描述

CMS(Concurrent Mark Sweep)

目前主流的互聯網企業選用的垃圾收集器. 使用標記-清除算法的年老代併發收集器

特性:

  • 低停頓
  • 無法處理浮動垃圾
  • 標記-清理算法造成碎片

收集過程:

  • 初始標記
    需要暫停其他線程, 標記一下GC Roots能夠直接關聯到的對象, 速度很快.
  • 併發標記
    併發執行, 進行GC Roots Tracing可達性分析, 對非直接關聯對象進行標記, 耗時長
  • 重新標記
    暫停其他線程, 併發修正併發標記產生變動的對象的記錄.
  • 併發清理
    併發運行, 清理標記的對象.

整個過程耗時最長的併發標記和併發清理都是併發執行的, 因此可以認爲CMS是與用戶線程併發執行的.

在這裏插入圖片描述

特點:

  • CMS啓動回收線程數=(CPU數目 + 3) /4 對CPU資源敏感.
  • 無法處理浮動垃圾, 即在併發清理階段產生的垃圾無法清除, 需要等到下一次GC. 需要留給用戶線程內存空間, 預留的內存不夠產生Concurrent Mode Failure 導致Full GC, JVM啓動後備預案,臨時啓用Serial Old進行老年代垃圾收集.
    -XX:CMSInitiatingOccupancyFraction 剩餘空間觸發垃圾收集的百分比.
  • 標記-清理法產生大量碎片 -XX: CMSFullGCsBeforeCompaction 設置執行多少次不帶壓縮的Full GC後,運行一次帶壓縮的GC

G1收集器

款面向服務端應用的收集器,主要目標用於配備多顆 CPU 的服務器治理大內存.

整個Java堆劃分成爲多個大小相等的區域Region, 新生代和年老代是一部分Region的集合.

根據每個Region裏面垃圾堆積的價值大小, 維護一個優先列表, 每次根據列表回收價值最大的Region, 保證了回收的效率.

建立Remembered Set 避免不同Region和區域間的對象引用. 每個Region都有一個Remembered Set, 當對引用進行操作時會維護被引用對象所屬的Region的Remembered Set.

特點:

  • 並行與併發: 充分利用多CPU多核環境, 縮短Stop the World的時間.
  • 分代收集: 能夠採用不同的方式去處理新創建的對象和已經存活了一段時間的多謝和熬過了多次GC的多謝.
  • 空間整合: 整體來看是給予標記-整理算法, 局部Region來看是基於複製算法. 因此運行期間不會產生碎片.
  • 可以預測的停頓. 低停頓是G1和CMS共同的關注點, G1還能建立可預測的停頓時間模型, 能夠制定一個長度的時間片, 是垃圾收集不超過該時間.

收集過程:

  • 初始標記
    需要暫停其他線程, 標記一下GC Roots能夠直接關聯到的對象, 速度很快.
  • 併發標記
    併發執行, 進行GC Roots Tracing可達性分析, 對非直接關聯對象進行標記, 耗時長
  • 最終標記
    需要暫停其他線程, 修正併發標記階段因用戶線程繼續運行而導致標記發生變化的那部分對象的標記記錄。
  • 篩選回收
    對每個Region的回收價值和成本進行排序, 根據用戶期望的GC停頓時間進行回收.

參考:《深入理解Java虛擬機》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章