jvm系列二之GC收集器
目錄
- 參考
- 概念理解
- 并發和并行
- 吞吐量
- GC垃圾收集器
- Serial New收集器
- Parallel New(并行)收集器
- Parallel Scavenge(并行)收集器
- Serial Old(串行)收集器
- Parallel Old(并行)收集器
- CMS收集器
- G1收集器(JDK)
參考
發現有個作者整理的已經很詳細了,筆者僅做一些簡單的修改記錄在這里,方便查閱自己的理解。原文《java垃圾收集器》基本是對《深入理解java虛擬機》一書的總結。另外筆者還參考了Java Garbage Collection Basics。
概念理解
并發和并行
這兩個名詞都是并發編程中的概念,在談論垃圾收集器的上下文語境中,它們可以解釋如下。
并行(Parallel):指多條垃圾收集線程并行工作,但此時用戶線程仍然處于等待狀態。
并發(Concurrent):指用戶線程與垃圾收集線程同時執行(但不一定是并行的,可能會交替執行),用戶程序在繼續運行,而垃圾收集程序運行于另一個CPU上。
雖然原書是這么講的,總感覺不對,所以查閱了文檔,私以為只是作者沒有描述清楚
吞吐量
吞吐量就是CPU用于運行用戶代碼的時間與CPU總消耗時間的比值,即吞吐量 = 運行用戶代碼時間 /(運行用戶代碼時間 + 垃圾收集時間)。
虛擬機總共運行了100分鐘,其中垃圾收集花掉1分鐘,那吞吐量就是99%。
GC垃圾收集器
圖中展示了7種作用于不同分代的收集器,如果兩個收集器之間存在連線,就說明它們可以搭配使用。虛擬機所處的區域,則表示它是屬于新生代收集器還是老年代收集器。
Serial New收集器
特性
- 最基本的收集器
- 針對新生代的收集器,采用的是復制算法
- 單線程
- 能與CMS收集器配合工作
優勢
簡單而高效(與其他收集器的單線程比),對于限定單個CPU的環境來說,Serial收集器由于沒有線程交互的開銷,專心做垃圾收集自然可以獲得最高的單線程收集效率。
應用場景
Serial收集器是虛擬機運行在Client模式下的默認新生代收集器。
Parallel New(并行)收集器
特性
- 使用多線程進行垃圾收集(Serial的多線程版本)
- 新生代采用復制算法,老年代采用標記整理
- 能與CMS收集器配合工作
- -XX:UseConcMarkSweepGC的默認新生代收集器
- 可以通過-XX:UseParNewGC選項強制指定
- -XX:ParallelGCThreads參數可以限制垃圾收集線程數
應用場景
ParNew收集器是許多運行在Server模式下的虛擬機中首選的新生代收集器。
主要原因是:除了Serial收集器外,目前只有它能與CMS收集器配合工作。
Parallel Scavenge(并行)收集器
- 與ParNew類似的是,都是用于年輕代回收的使用復制算法的并行收集器
- 該收集器的目標是達到一個可控制的吞吐量,其中吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)
- Parallel Scavenge提供了兩個參數用以精確控制吞吐量,分別是用以控制最大GC停頓時間的-XX:MaxGCPauseMillis及直接控制吞吐量的參數-XX:GCTimeRatio.
- MaxGCPauseMiilis:單位為ms,適用于高用戶體驗的場景,虛擬機將盡力保證每次MinorGC耗時不超過所設時長,但并不是該時間越小越好,因為GC耗時縮短是用調小年輕代獲取的,回收500m的對象肯定要比回收2000m的對象耗時更短,但是回收頻率也大大增大了,吞吐量也隨之下去了。使用該參數的理論效果:MaxGCPauseMillis越小,單次MinorGC的時間越短,MinorGC次數增多,吞吐量降低。
- GCTimeRatio:從字面意思上理解是花費在GC上的時間占比,但是實際含義并非如此,GC耗時的計算公式為1/(1+n),n為GCTimeRatio,因此,GCTimeRatio的實際用途是直接指定吞吐量。GCTimeRatio的默認值為99,因此,GC耗時的占比應為1/(1+99)=1%。使用參數的理論效果:GCTimeRatio越大,吞吐量越大,GC的總耗時越小。有可能導致單次MinorGC耗時變長。適用于高運算場景。
- 此外,還有個參數和以上兩個參數息息相關,那就是-XX:+UseAdaptiveSizePolicy,默認為啟用,搭配MaxGCPauseMillis或GCTimeRatio使用,打開該開關后,虛擬機將根據當前系統運行情況收集性能監控信息,動態調整SurvivorRatio,PretenureSizeThreshold等細節參數。
使用場景
該收集器是server模式下的默認收集器,也可-XX:+UseParallelGC強制使用該收集器,打開該收集器后,將使用Parallel Scavenge(年輕代)+Serial Old(老年代)的組合進行GC。
Serial Old(串行)收集器
特性
Serial New收集器的老年代版本,使用用標記整理算法
使用場景
主要意義是提供給client模式下的虛擬機用。
虛擬機在Server模式下有兩大用途:
Parallel Old(并行)收集器
特性
- Parallel Scavenge收集器的老年代版本
- 針對老年代,多線程,標記整理算法
使用場景
在注重吞吐量以及CPU資源敏感的場合,都可以優先考慮Parallel Scavenge加Parallel Old收集器。
這個收集器是在JDK 1.6中才開始提供的,在此之前,新生代的Parallel Scavenge收集器一直處于比較尷尬的狀態。原因是,如果新生代選擇了Parallel Scavenge收集器,老年代除了Serial Old收集器外別無選擇(Parallel Scavenge收集器無法與CMS收集器配合工作)。由于老年代Serial Old收集器在服務端應用性能上的“拖累”,使用了Parallel Scavenge收集器也未必能在整體應用上獲得吞吐量最大化的效果,由于單線程的老年代收集中無法充分利用服務器多CPU的處理能力,在老年代很大而且硬件比較高級的環境中,這種組合的吞吐量甚至還不一定有ParNew加CMS的組合“給力”。直到Parallel Old收集器出現后,“吞吐量優先”收集器終于有了比較名副其實的應用組合。
CMS收集器
特性
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。目前很大一部分的Java應用集中在互聯網站或者B/S系統的服務端上,這類應用尤其重視服務的響應速度,希望系統停頓時間最短,以給用戶帶來較好的體驗。CMS收集器就非常符合這類應用的需求。
運作過程
CMS收集器是基于“標記—清除”算法實現的,它的運作過程相對于前面幾種收集器來說更復雜一些,整個過程分為4個步驟:
初始標記(CMS initial mark)
初始標記僅僅只是標記一下GC Roots能直接關聯到的對象,速度很快,需要“Stop The World”。
并發標記(CMS concurrent mark)
并發標記階段就是進行GC Roots Tracing的過程。
重新標記(CMS remark)
重新標記階段是為了修正并發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間一般會比初始標記階段稍長一些,但遠比并發標記的時間短,仍然需要“Stop The World”。
并發清除(CMS concurrent sweep)
并發清除階段會清除對象。
由于整個過程中耗時最長的并發標記和并發清除過程收集器線程都可以與用戶線程一起工作,所以,從總體上來說,CMS收集器的內存回收過程是與用戶線程一起并發執行的。
優點
CMS是一款優秀的收集器,它的主要優點在名字上已經體現出來了:并發收集、低停頓。
缺點
1.CMS收集器對CPU資源非常敏感
其實,面向并發設計的程序都對CPU資源比較敏感。在并發階段,它雖然不會導致用戶線程停頓,但是會因為占用了一部分線程(或者說CPU資源)而導致應用程序變慢,總吞吐量會降低。
CMS收集器無法處理浮動垃圾,可能出現“Concurrent Mode Failure”失敗而導致另一次Full GC的產生。由于CMS并發清理階段用戶線程還在運行著,伴隨程序運行自然就還會有新的垃圾不斷產生,這一部分垃圾出現在標記過程之后,CMS無法在當次收集中處理掉它們,只好留待下一次GC時再清理掉。這一部分垃圾就稱為“浮動垃圾”。也是由于在垃圾收集階段用戶線程還需要運行,那也就還需要預留有足夠的內存空間給用戶線程使用,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進行收集,需要預留一部分空間提供并發收集時的程序運作使用。要是CMS運行期間預留的內存無法滿足程序需要,就會出現一次“Concurrent Mode Failure”失敗,這時虛擬機將啟動后備預案:臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,這樣停頓時間就很長了。
CMS是一款基于“標記—清除”算法實現的收集器,這意味著收集結束時會有大量空間碎片產生??臻g碎片過多時,將會給大對象分配帶來很大麻煩,往往會出現老年代還有很大空間剩余,但是無法找到足夠大的連續空間來分配當前對象,不得不提前觸發一次Full GC。
G1收集器(JDK)
Getting Started with the G1 Garbage Collector
堆內存分配
G1的堆內存被分成許多固定大小的區域。區域大小相同,在JVM啟動時確定。JVM通常管理2000個區域,區域大小介于1M到32M之間。
這些區域被映射為邏輯上的Eden、survivor和老年代區域,相同類型區域地址可以不連續。
區域分為五種,Eden、survivor和老年代,另外還有一種大對象區(Humongous),Humongous區域用來存放占據50%以上區域空間的對象,這些對象被存儲在一組連續區域內,最后一種區域就是未被使用區域。
G1的Young GC
存活對象移動到一個或多個survivor區域。如果對象達到晉升年齡,將被移動到老年代區域。這一階段會Stop The World(STW)。
G1老年代垃圾回收
G1回收器在對內存的老年代區域執行以下階段。注意這些階段也包括新生代的回收。
| 初始標記(STW) | 捎帶一次youngGC。標記可能引用了老年代區域對象的survivor區域(根區域) |
| 根區域掃描 | 掃描根區域中指向老年代的引用。與應用線程并發。此階段完成后才可以進行youngGC |
| 并發標記 | 全堆掃描存活對象。與應用線程并發。這一階段可以被youngGC打斷 |
| 重新標記STW | 完成堆中所有存活對象的掃描,使用snapshot-at-the-beginningSATB算法 |
| 清除 | 統計存活對象和空區域(STW),更新RSets(STW),重置空區域,加入空白列表(并發) |
| 復制STW | 將存活對象移動至未使用區域 |
轉載于:https://www.cnblogs.com/mcai/p/9642377.html
總結
以上是生活随笔為你收集整理的jvm系列二之GC收集器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中兴 F50 随身 Wi-Fi 开启预售
- 下一篇: 山姆会员卡多少钱(在山姆办会员卡的人)