【JVM】垃圾回收器總結(2)——七種垃圾回收器型別

xd會飛的貓發表於2020-06-03

七種垃圾回收器型別

GC的約定引數

DefNew——Default New Generation

Tenured——Serial Old

ParNew——Parallel New Generation

PSYoungGen——Parallel Scavenge

ParOldGen——Parallel Old Generation

適用範圍:只需要掌握Server模式,Client模式基本不會用。

作業系統:32位windows不論硬體如何預設使用Client模式。32位其他OS,2G記憶體同時2個CPU以上用Server模式,低於該配置是Client模式。64位只有Server模式。

七大垃圾收集器

序列GC:Serial收集器(1:1)

序列收集器是最古老的,最穩定,效率高的收集器,只使用一個執行緒去回收但其進行垃圾回收過程中可能會產生較長的停頓。雖然在收集垃圾的過程中需要暫停其他的工作執行緒,但是簡單高效,對於單CPU環境來說,沒有執行緒互動的開銷可以獲得最高的單執行緒垃圾收集效率,因此Serial垃圾回收器依然是Java虛擬機器執行在Client模式下預設的新生代垃圾回收器。

開啟序列收集器的JVM引數是-XX:+UseSerialGC。

開啟後會使用:Serial(Young區)+ Serial Old(Old區)的收集器組合。表示新生代、老年代都會使用序列回收收集器,新生代用複製演算法,老年代用標記整理演算法。

顯式啟用垃圾回收器:

並行GC:ParNew(N:1)

使用多執行緒進行垃圾回收,在垃圾回收時,會暫停所有其他工作執行緒,直到GC結束。

ParNew時Serial收集器新生代的並行多執行緒版本,最常見的應用場景是配合老年代CMS GC工作,其餘行為和Seria收集器完全一樣,ParNew垃圾收集器在垃圾收集過程中同樣要暫停所有其他的工作執行緒。它是很多JVM執行在Server模式下新生代的預設垃圾收集器。

開啟序列收集器的JVM引數是-XX:+UseParNewGC。

啟用ParNew收集器,隻影響新生代的收集(新生代GC頻繁),不影響老年代。開啟引數後,會使用ParNew(Young區)+Serial(Old區)的收集器組合。新生代使用複製演算法,老年代使用標記整理演算法。

ParNew+Tenured(Serial Old)不再推薦使用:

並行回收:Parallel Scavenge(N:N)

Parallel Scavenge收集器類似ParNew,也是一個新生代垃圾收集器,使用複製演算法,也是一個並行的多執行緒的垃圾收集器,俗稱吞吐量優先收集器。相當於是序列收集器在新生代和老年代的並行化。

它重點關注可控制吞吐量,高吞吐量意味著高效利用CPU時間,它多用於在後臺運算而不需要太多互動的任務。【吞吐量  = 使用者程式碼執行時間/(使用者程式碼執行時間+垃圾回收時間)】

自適應調節策略也是Parallel Scavenge收集器與ParNew收集器的一個重要區別。自適應調節策略就是JVM會根據當前系統的執行情況看收集效能監控資訊,動態調整這些引數以提供最合適的停頓時間(-XX: MaxGCPauseMills)或最大吞吐量。

常用的JVM引數:-XX:+UseParallelGC 或者 +UseParallelOldGC(二者可以互相啟用),使用Parallel Scavenge收集器。開啟引數後,新生代用複製演算法,老年代用複製標記整理演算法。

引數-XX:+ParallelGCThread = K 表示啟動K個GC執行緒【CPU > 8  K = 5或8 CPU < 8 K = 實際個數】

Parallel Old收集器

Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多執行緒的標記整理演算法,在JDK1.6開始提供。

JDK1.6之前,新生代使用Parallel Scavenge收集器只能搭配老年代Serial Old收集器,只能保證新生代的吞吐量優先,無法保證整體的吞吐量。在JDK1.6之前,是Parallel Scavenge+Serial Old。

Parallel Old是為了老年代同樣提供吞吐量優先的垃圾收集器,如果系統對吞吐量要求較高,JDK1.8後優先考慮新生代Parallel Scavenge和老年代 Parallel Old的搭配策列。在JDK1.8及之後,是Parallel Scavenge+Parallel Old。

JVM常用引數:-XX:+UseParallelOldGC使用Parallel Old收集器。和上一個part的截圖是一致的,UseParallelGC和UseParallelOldGC可以互相啟用。

併發標記清除GC(CMS)

CMS收集器是一個以獲取最短回收停頓時間為目標的收集器。適合應用在網際網路站或BS系統的伺服器上,因為這類場景重視伺服器的響應速度,希望系統的停頓時間儘可能短。CMS適合堆記憶體大、CPU核數多的伺服器端應用,也是G1出現之前大型應用的首選收集器。

CMS的優勢是併發收集停頓少,併發是指與使用者執行緒一起執行。

開啟收集器的JVM引數:-XX:+UseConcMarkSweepGC 開啟後會自動開啟 -XX:+UseParNewGC

併發標記清除收集器的組合:ParNew + CMS + Serial Old(作為CMS出錯的後備收集器,增強健壯性)

CMS記憶體回收一共有4個過程

  1. 初始標記:只有標記一下GC Roots能直接關聯的物件,速度很快,仍然需要暫停所有的工作執行緒。
  2. 併發標記:進行GC Roots跟蹤的過程,和使用者執行緒一起工作,不需要暫停工作執行緒,主要標記過程,標記全部物件。
  3. 重新標記:修正在併發標記期間,因使用者程式繼續執行而導致標記產生變動的那一部分物件的標記記錄,仍然需要暫停所有的工作執行緒。由於併發標記時,使用者執行緒依然執行,因此在正式清理前再做修正。
  4. 併發清除:清除GC Roots不可達物件,和使用者執行緒一起工作,不需要暫停工作執行緒。基於標記結果,直接清理物件。由於耗時最長的併發標記和併發清除過程中,垃圾收集執行緒可以和使用者執行緒一起併發工作。所以總體上說CMS收集器的記憶體回收和使用者執行緒是併發執行的(初始標記和重新標記雖然要暫停,但是用時很短)。

優點:併發收集,停頓次數少。

缺點:對CPU的壓力大,CMS在收集和應用執行緒會同時增加對堆記憶體的佔用,也就是i說CMS必須在老年代堆記憶體用完之前完成GC,否則CMS會回收失敗,將觸發擔保機制,Serial Old會以STW(Stop The World,暫停所有工作執行緒)的方式進行依次GC,從而造成較大的停頓時間。而且採用標記清除演算法會產生記憶體碎片。

Serial Old收集器

Serial Old收集器是Serial垃圾收集器老年代版本,同樣是單執行緒的收集器,使用標記整理演算法。

主要執行在Client預設的JVM老年代垃圾回收器。

在Server模式下,主要有兩個用途:

  1. 在JDK1.5之前與新生代Parallel Scavenge收集器搭配使用。(Parallel Scavenge+Serial Old)
  2. 作為老年代版中使用CMS收集器的後備垃圾回收方案。

G1垃圾回收器

內容較多,見【JVM】垃圾回收器總結(3)

相關文章