新生代收集器使用的收集器:Serial、PraNew、Parallel Scavenge算法
老年代收集器使用的收集器:Serial Old、Parallel Old、CMS服務器
Serial收集器是Hotspot運行在Client模式下的默認新生代收集器, 它的特色是:只用一個CPU(計算核心)/一條收集線程去完成GC工做, 且在進行垃圾收集時必須暫停其餘全部的工做線程(「Stop The World」 -後面簡稱STW)。可使用-XX:+UseSerialGC打開。多線程
雖然是單線程收集, 但它卻簡單而高效, 在VM管理內存不大的狀況下(收集幾十M~一兩百M的新生代), 停頓時間徹底能夠控制在幾十毫秒~一百多毫秒內。併發
ParNew收集器實際上是前面Serial的多線程版本, 除使用多條線程進行GC外, 包括Serial可用的全部控制參數、收集算法、STW、對象分配規則、回收策略等都與Serial徹底同樣(也是VM啓用CMS收集器-XX: +UseConcMarkSweepGC的默認新生代收集器)。高併發
因爲存在線程切換的開銷, ParNew在單CPU的環境中比不上Serial, 且在經過超線程技術實現的兩個CPU的環境中也不能100%保證能超越Serial. 但隨着可用的CPU數量的增長, 收集效率確定也會大大增長(ParNew收集線程數與CPU的數量相同, 所以在CPU數量過大的環境中, 可用-XX:ParallelGCThreads=<N>參數控制GC線程數)。性能
與ParNew相似, Parallel Scavenge也是使用複製算法, 也是並行多線程收集器. 但與其餘收集器關注儘量縮短垃圾收集時間不一樣, Parallel Scavenge更關注系統吞吐量:spa
系統吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)線程
停頓時間越短就越適用於用戶交互的程序-良好的響應速度能提高用戶的體驗;而高吞吐量則適用於後臺運算而不須要太多交互的任務-能夠最高效率地利用CPU時間,儘快地完成程序的運算任務. Parallel Scavenge提供了以下參數設置系統吞吐量:對象
Parallel Scavenge參數blog |
描述 |
-XX:MaxGCPauseMillis |
(毫秒數) 收集器將盡力保證內存回收花費的時間不超過設定值, 但若是過小將會致使GC的頻率增長. |
-XX:GCTimeRatio |
(整數:0 < GCTimeRatio < 100) 是垃圾收集時間佔總時間的比率 |
XX:+UseAdaptiveSizePolicy |
啓用GC自適應的調節策略: 再也不須要手工指定-Xmn、-XX:SurvivorRatio、-XX:PretenureSizeThreshold等細節參數, VM會根據當前系統的運行狀況收集性能監控信息, 動態調整這些參數以提供最合適的停頓時間或最大的吞吐量 |
適合後臺應用等對交互相應要求不高的場景。
Serial Old是Serial收集器的老年代版本, 一樣是單線程收集器,使用「標記-整理」算法
Parallel Old是Parallel Scavenge收集器的老年代版本, 使用多線程和「標記-整理」算法, 吞吐量優先, 主要與Parallel Scavenge配合在注重吞吐量及CPU資源敏感系統內使用;
CMS(Concurrent Mark Sweep)收集器是一款具備劃時代意義的收集器, 一款真正意義上的併發收集器, 雖然如今已經有了理論意義上表現更好的G1收集器, 但如今主流互聯網企業線上選用的還是CMS(如Taobao、微店).
CMS是一種以獲取最短回收停頓時間爲目標的收集器(CMS又稱多併發低暫停的收集器), 基於」標記-清除」算法實現, 整個GC過程分爲如下4個步驟:
1. 初始標記(CMS initial mark)
2. 併發標記(CMS concurrent mark: GC Roots Tracing過程)
3. 從新標記(CMS remark)
4. 併發清除(CMS concurrent sweep: 已死對象將會就地釋放, 注意:此處沒有壓縮)
其中1,3兩個步驟(初始標記、從新標記)仍需STW. 但初始標記僅只標記一下GC Roots能直接關聯到的對象, 速度很快; 而從新標記則是爲了修正併發標記期間因用戶程序繼續運行而致使標記產生變更的那一部分對象的標記記錄, 雖然通常比初始標記階段稍長, 但要遠小於併發標記時間.
CMS特色:
1. CMS默認啓動的回收線程數=(CPU數目+3)4
當CPU數>4時, GC線程通常佔用不超過25%的CPU資源, 可是當CPU數<=4時, GC線程可能就會過多的佔用用戶CPU資源, 從而致使應用程序變慢, 總吞吐量下降.
2.沒法處理浮動垃圾, 可能出現Promotion Failure、Concurrent Mode Failure而致使另外一次Full GC的產生: 浮動垃圾是指在CMS併發清理階段用戶線程運行而產生的新垃圾. 因爲在GC階段用戶線程還需運行, 所以還須要預留足夠的內存空間給用戶線程使用, 致使CMS不能像其餘收集器那樣等到老年代幾乎填滿了再進行收集. 所以CMS提供了-XX:CMSInitiatingOccupancyFraction參數來設置GC的觸發百分比(以及-XX:+UseCMSInitiatingOccupancyOnly來啓用該觸發百分比), 當老年代的使用空間超過該比例後CMS就會被觸發(JDK 1.6以後默認92%). 但當CMS運行期間預留的內存沒法知足程序須要, 就會出現上述Promotion Failure等失敗, 這時VM將啓動後備預案: 臨時啓用Serial Old收集器來從新執行Full GC(CMS一般配合大內存使用, 一旦大內存轉入串行的Serial GC, 那停頓的時間就是你們都不肯看到的了).
3.最後, 因爲CMS採用」標記-清除」算法實現, 可能會產生大量內存碎片. 內存碎片過多可能會致使沒法分配大對象而提早觸發Full GC. 所以CMS提供了-XX:+UseCMSCompactAtFullCollection開關參數, 用於在Full GC後再執行一個碎片整理過程. 但內存整理是沒法併發的, 內存碎片問題雖然沒有了, 但停頓時間也所以變長了, 所以CMS還提供了另一個參數-XX:CMSFullGCsBeforeCompaction用於設置在執行N次不進行內存整理的Full GC後, 跟着來一次帶整理的(默認爲0: 每次進入Full GC時都進行碎片整理).
高併發、低停頓,追求最短GC回收停頓時間,cpu佔用比較高,響應時間快,停頓時間短,多核cpu 追求高響應時間的選擇
G1(Garbage-First)是一款面向服務端應用的收集器, 主要目標用於配備多顆CPU的服務器治理大內存.
- G1 is planned as the long term replacement for the Concurrent Mark-Sweep Collector (CMS).
-XX:+UseG1GC啓用G1收集器.
與其餘基於分代的收集器不一樣, G1將整個Java堆劃分爲多個大小相等的獨立區域(Region), 雖然還保留有新生代和老年代的概念, 但新生代和老年代再也不是物理隔離的了, 它們都是一部分Region(不須要連續)的集合.如:
每塊區域既有可能屬於O區、也有多是Y區, 所以不須要一次就對整個老年代/新生代回收. 而是當線程併發尋找可回收的對象時, 有些區塊包含可回收的對象要比其餘區塊多不少. 雖然在清理這些區塊時G1仍然須要暫停應用線程, 但能夠用相對較少的時間優先回收垃圾較多的Region. 這種方式保證了G1能夠在有限的時間內獲取儘量高的收集效率.
G1的新生代收集跟ParNew相似: 存活的對象被轉移到一個/多個Survivor Regions. 若是存活時間達到閥值, 這部分對象就會被提高到老年代.如圖:
其特定是:
一整塊堆內存被分爲多個Regions.
存活對象被拷貝到新的Survivor區或老年代.
年輕代內存由一組不連續的heap區組成, 這種方法使得能夠動態調整各代區域尺寸.
Young GC會有STW事件, 進行時全部應用程序線程都會被暫停.
多線程併發GC.
G1老年代GC特色以下:
併發標記階段
1 在與應用程序併發執行的過程當中會計算活躍度信息.
2 這些活躍度信息標識出那些regions最適合在STW期間回收(which regions will be best to reclaim during an evacuation pause).
3 不像CMS有清理階段.
再次標記階段
1 使用Snapshot-at-the-Beginning(SATB)算法比CMS快得多.
2 空region直接被回收.
拷貝/清理階段(Copying/Cleanup Phase)
1 年輕代與老年代同時回收.
2 老年代內存回收會基於他的活躍度信息.