上一篇文章中學習了 JVM
的垃圾回收機制,和內存分配和回收策略。不過這都是一些理論知識,這篇文章中會學習一下 HotSpot
虛擬機中的垃圾收集器,這都是垃圾回收理論的具體實現。html
HotSpot
虛擬機中有多種收集器,不一樣的收集器特色也不一樣,各年代使用的收集器也能夠根據應用的特色和要求進行組合。算法
Serial
收集器是一個單線程的收集器,它不只只會使用一個 CPU
或一條收集線程去完成垃圾收集工做,並且在垃圾收集時,必須暫停其餘全部的工做線程,直到它收集結束。多線程
Serial
收集器是 HotSpot
虛擬機在運行 Client
模式下的默認新生代收集器。在垃圾收集時,年輕代使用「複製」算法,老年代使用「標記-整理」算法。併發
但它也有優勢,與其餘收集器的單線程相比,因爲沒有現成交互的開銷,專心作垃圾收集,因此其簡單而高效;性能
可使用 -XX:UseSerialGC
參數選擇使用 Serial
收集器,此時年輕代採用 Serail
,老年代採用 Serial Old
。學習
ParNew
收集器是 Serial
收集器的多線程版本,除了使用多線程進行垃圾回收外,其餘幾乎同樣。線程
它是許多運行在 Server
模式下的虛擬機首選的新生代收集器,一個很重要的緣由是除了 Serial
收集器外,只有 ParNew
收集器與 CMS
收集器配合工做。垃圾收集時,年輕代使用「複製」算法,老年代使用「標記-整理」算法。code
ParNew
收集器默認開啓的線程數與 CPU
的數量相同,可使用 -XX:ParallelGCThreas
參數來限制垃圾收集的線程數。使用 -XX:UseParNewGC
參數來使用 ParNew
收集器。cdn
Parallel Scavenge
收集器是新生代收集器,也是使用複製算法的多線程收集器。與其餘收集器不一樣的是,它關注的是達到一個可控制的吞吐量,吞吐量 = 運行代碼時間 / (運行代碼時間 + 垃圾收集時間)。htm
Parallel Scanenge
收集器提供了兩個參數用於精確控制吞吐量。第一個是控制最大垃圾收停頓時間的 -XX:MaxGCPauseMillis
參數。它容許是一個大於 0
的毫秒數,收集器將盡量保證內存回收時間不超過設定值。這個參數也不是越小越好,GC 停頓時間縮短是以犧牲吞吐量和新生代空間爲代價換取的。
第二個是直接設置吞吐量大小的 -XX:GCTimeRatio
參數。它容許是一個大於 0
且小於 100
的整數,就是垃圾收集時間佔總時間的比率。
另外,Parallel Scavenge
收集器擁有自適應調節機制,它不須要手工指定新生代的大小(-Xmn
)、Eden
與 Survivor
區的比例(-XX:SurvivorRatio
)、晉升老年代對象大小 -XX:PretenureSizeThreshold
等細節參數,虛擬機會根據當前系統的運行狀況收集性能監控信息,動態調整參數以提供最合適的停頓時間及最大的吞吐量。可以使用 -XX:UseAdaptiveSizePolicy
參數來開啓。
Serial Old
是 Serial
收集器的老年代版本,是一個單線程收集器,使用「標記-整理算法」。
Parallel Old
是 Parallel Scavenge
收集器的老年代版本,使用多線程和「標記-整理」算法。若是新生代選擇了 Parallel Scavenge
收集器,老年代只能選擇 Serial Old
收集器。
CMS(Concurrent Mark Sweep)
是一種以獲取最短停頓時間爲目標的收集器,使用「標記-清除」算法。若是應用重視響應速度,但願停頓時間最短,就能夠選擇 CMS
收集器。
它的運做過程可分爲 4
個步驟:
GC Roots
能直接關聯到的對象,速度很快,須要 Stop the world
。GC Roots Tracing
過程。CMS
的主要優勢是併發收集、低停頓。但也有三個缺點:
CPU
資源很是敏感。併發階段雖不會致使用戶線程停頓,但會由於佔用資源而致使程序變慢,總吞吐量下降。Concurrent Mode Failure
失敗而致使另外一次 Full FC
的產生。CMS
基於標記-清除算法,收集結束時會產生大量空間碎片。碎片過多時,沒法找到足夠的連續空間來分配大對象,不得不提早出發一次 Full GC
。可使用 -XX:UseConcMarkSweepGC
參數來選擇 CMS
收集器。
G1(Garbage-First)
是一款面向服務端應用的垃圾收集器。它的特色以下:
CPU
、多核環境,使用多個 CPU
來縮短停頓的時間,部分須要其餘收集器本來須要停頓 Java
線程執行的 GC
動做,G1
收集器可經過併發的方式讓 Java
程序繼續執行。G1
收集器能獨立管理整個 GC
堆,而且能採用不一樣的方式處理不一樣時期的對象。G1
收集器從總體來看,基於「標記-整理」算法實現;從局部來看,基於「複製」算法實現。G1
能明確指定垃圾收集的限制時間。使用 G1
收集器時,將 Java
堆劃分爲多個大小相等的區域 Region
。G1
跟蹤各個 Region
的回收價值和成本(回收得到空間及回收時間),後臺會維護一個優先列表,每次根據容許的收集時間,優先回收價值最大的 Region
。它經過使用 Remembered Set
來避免全堆掃描。
G1
收集器的運行步驟可分爲:
GC Roots
直接能關聯到的對象,須要停頓,但耗時很短。GC Roots
開始對堆中對象進行可達性分析,找出存活的對象,耗時較長,但可併發執行。Region
的回收價值和成本進行排序,根據指定的 GC
停頓時間制定回收計劃。HotSpot
虛擬機中包含了七種垃圾收集器,以下圖:
它們的組合說明以下:
新生代收集器 | 年老代收集器 | 說明 |
---|---|---|
Serial | Serial Old | 都是單線程,GC 時會暫停全部應用線程。 使用 -XX:+UseSerialGC 選項來開啓 |
Serial | CMS + Serial Old | CMS 是併發 GC,不須要暫停全部應用線程。 當 CMS 進行 GC 失敗時,會自動使用 Serial Old 策略進行 GC 使用 -XX:+UseConcMarkSweepGC 選項來開啓 |
ParNew | CMS | ParNew 是 Serial 的並行版本,能夠指定 GC 線程數 默認 GC 線程數爲 CPU 的數量 |
ParNew | Serial Old | 使用 -XX:+UseParNewGC 選項來開啓 |
Parallel Scavenge | Serial Old | Parallel Scavenge 策略關注吞吐量,適用於後臺持久運行的應用程序 使用 -XX:+UseParallelGC 選項來開啓 |
Parallel Scavenge | Parallel Old | Parallel Old 是 Serial Old 的並行版本 使用 -XX:+UseParallelOldGC 選項來開啓 |
G1GC | G1GC | -XX:+UseG1GC #開啓 -XX:MaxGCPauseMillis #暫停時間目標 |