若是說垃圾收集算法是內存回收的方法論,那垃圾收集器就是內存回收的實踐者。本次要介紹的是幾款「經典」的垃圾收集器,之因此被稱之爲「經典」,是爲了與幾款目前仍處於實驗狀態,可是執行效果上喲革命性改進的高性能低延遲收集器區分開來,雖然算不上最早進的技術,但倒是在實踐中千錘百煉,足夠成熟,能夠在商用生產環境上放心使用的所有垃圾收集器。
這些「經典」收集器之間的關係圖
這七種做用於不一樣分代的收集器,若是兩個之間存在連續,說明能夠搭配使用。目前這些垃圾收集器並不都是「萬能」的,因此針對於各個垃圾收集器,咱們的目的是根據本身的具體場景而去選擇合適的收集器。算法
Serial收集器是最基礎、歷史最悠久的收集器,曾經(在JDK1.3.1以前)是HotSpot虛擬機新生代收集器的惟一選擇。這個收集器是一個單線程工做的收集器,在進行垃圾收集時,必須暫停其餘全部工做現場,直到它收集結束。
Serial/Serial Old收集器的運行過程。
對於這個收集器,雖然是單線程而且須要在暫停其餘全部工做線程。但這個收集器卻並非已經被拋棄或是過期的,由於它有着優於其餘收集器的地方,那就是簡單高效(與其餘收集器的單線程相比)。對於內存資源受限的環境,它是全部收集器裏額外內存消耗最小的;對於單核處理器或處理器核心數較少的環境來講,Serial收集器因爲沒有線程交互的開銷,專心作垃圾收集自如能夠得到最高的線程收集效率。多線程
ParNew收集器實質上Serial收集器的多線程並行版本,除了同時使用多條線程進行垃圾收集以外,其他的行爲包括Serial收集器可用的全部控制參數、收集算法、Stop The World、對象分配規則、回收策略等都與Serial收集器徹底一致,在實現上也是共用了至關多的代碼。
ParNew收集器的工做過程示意圖:
ParNew收集器除了支持多線程並行收集以外,其餘與Serial收集器相比並無太多創新之處。可是它有一個與功能、性能無關卻很重要的優點,除了Serial收集器外,目前只有它能與CMS收集器配合工做。可是隨着G1收集器的出現,從JKD9開始,官方已經再也不推薦ParNew和CMS這種組合了,因此ParNew也就慢慢開始退出歷史舞臺了。併發
Parallel Scavenge收集器也是一款新生代收集器,它一樣是基於標記-複製算法實現的收集器,也是可以並行收集的多線程收集器。這款收集器的關注點和其餘收集器不一樣,其餘收集器的關注點是儘量的縮短用戶線程停頓時間,而Parallel Scavenge收集器的目標則是到達一個可控制的 吞吐量。 所謂吞吐量就是處理器用於運行用戶代碼的時間與處理器總消耗時間的比值。
Parallel Scavenge收集器的運行示意圖
Parallel Scavenge收集器提供了兩個參數用於精確控制吞吐量,分別是控制最大攔擊收集停頓時間的-XX:MaxGCPauseMilis參數以及直接這是吞吐量大小的-XX:GCTimeRatio參數。
-XX:MaxGCPauseMilis參數運行的值是一個大於0的毫秒數,收集器將盡可能保證內存回收花費的時間不超過用戶設定值。
-XX:GCTimeRatio參數的值則應當是一個大於0小於100的整數,也就是垃圾收集時間佔總時間的比率,至關於吞吐量的倒數。
Parallel Scavenge收集器還有一個參數-XX:+UserAdaptiveSizePolicy值得咱們關注。這是一個開關參數,在被激活以後就不須要人工置頂Eden去與Survivor區的比率、以及晉升老年代對象大小等細節參數了。虛擬機會根據運行狀況自行調節。自適應調節策略也是Parallel Scavenge收集器區別於ParNew收集器的一個重要特性。佈局
Serial Old收集器是Serial 收集器的老年代版本,也是一個單線程收集器,一樣適用標記-整理算法。這個收集器的主要意義也是提供客戶端模式下的HotSpot虛擬機使用。
Serial Old運行示意圖:
若是在服務端模式下,Serial Old收集器可能有兩種用途:一種是在JDK5以及以前的版本中與Parallel Scavengen收集器搭配使用,另一種就是做爲CMS收集器發送失敗時的後備預案,在併發收集發生Concurrent Mode Failure 時使用。性能
Parallel Old是Parallel Scavenge收集器的老年代版本,支出多線程併發收集,基於標記-整理算實現。這個收集器是在JDK6時才提供的,以前新生代選擇了Parallel Scavenge收集器,老年代只能選擇Serial Old(PS MarkSweep)收集器。
直到Parallel Old 收集器出現後,「吞吐量優先」收集器終於有了筆記名副其實的搭配組合,在注重吞吐量或者處理器資源較爲稀缺的場合,均可以優先考慮Parallel Scavenge加Parallel Old收集器這個組合。
Parallel Old收集器工做示意圖:
spa
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間爲目標的收集器。
CMS是基於標記-清除算法實現的,可是整個運做過程相對於前面幾種收集器來講要複雜一些,整個過程分四步驟:
一、初始標記(CMS initial mark)
二、併發標記(CMS concurrent mark)
三、從新標記(CMS remark)
四、併發清除(CMS concurrent sweep)
初始標記、從新標記這兩個步驟仍然須要中止用戶線程。線程
Garbage First(簡稱G1)收集器是垃圾收集器技術發展歷史上的里程碑是的成果,它開創了收集器面向局部收集的設計思路和基於Region的內存佈局形式。
G1是一款主要面向服務端應的垃圾收集器。HotSpot開發團隊最初賦予它的指望是替換CMS收集器。從JDK9發佈之日,G1宣告取代Parallel Scavenge 加Parallel Old組合,稱爲服務端模式下的默認的垃圾收集器。
G1開創了基於Region的堆內存佈局是它可以實現能夠由用戶指定用戶線程停頓時間的關鍵。雖然G1也遵循分代收集的設計理論,但卻再也不堅持固定大小以及固定數量的分代區域劃分,而是把連續的Java堆劃分爲多個大小相等的獨立區域(Region),每個Region採用不一樣的策略去處理,這樣無理是新建立的對象仍是已經存活了一段時間、熬過屢次收集的舊對象都能獲取很好的收集效果。
G1收集器的分區示意圖:
若是咱們不去計算用戶線程運行過程當中的動做,G1收集器的運做過程大體可劃分爲如下四個步驟:設計
最後結合上節說的垃圾收集算法總結一下:指針
垃圾收集算法 | 垃圾收集器 | ||
---|---|---|---|
標記-清除 | CMS | ||
標記-複製 | Serial | ParNew | Parallel Scavenge |
標記-整理 | Serial Old | Parallel Old | G1 |