1. 程式人生 > >java總結——JVM垃圾回收器、回收演算法、垃圾回收器使用場景

java總結——JVM垃圾回收器、回收演算法、垃圾回收器使用場景

這裡寫圖片描述

圖中展示了7種不同分代的收集器:
Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1;

新生代收集器:Serial、ParNew、Parallel Scavenge;
老年代收集器:Serial Old、Parallel Old、CMS;
整堆收集器:G1;

兩個收集器間有連線,表明它們可以搭配使用:

Serial/Serial Old、Serial/CMS、ParNew/Serial Old、ParNew/CMS、Parallel Scavenge/Serial Old、Parallel Scavenge/Parallel Old、G1;

1.Serial收集器

Serial收集器是最基本、發展歷史最悠久的收集器。是單執行緒的收集器。它在進行垃圾收集時,必須暫停其他所有的工作執行緒,直到它收集完成。

Serial收集器依然是虛擬機器執行在Client模式下預設新生代收集器,對於執行在Client模式下的虛擬機器來說是一個很好的選擇。

2.ParNew收集器

ParNew收集器其實就是Serial收集器的多執行緒版本,除了使用多執行緒進行垃圾收集之外,其餘行為包括Serial收集器可用的所有控制引數、收集演算法、Stop The Worl、物件分配規則、回收策略等都與Serial 收集器完全一樣。

ParNew收集器是許多執行在Server模式下的虛擬機器中首選新生代收集器,其中有一個與效能無關但很重要的原因是,除Serial收集器之外,目前只有ParNew它能與CMS收集器配合工作

3.Parallel Scavenge(並行回收)收集器

Parallel Scavenge收集器是一個新生代收集器,它也是使用複製演算法的收集器,又是並行的多執行緒收集器該收集器的目標是達到一個可控制的吞吐量(Throughput)。所謂吞吐量就是CPU用於執行使用者程式碼的時間與CPU總消耗時間的比值,即 吞吐量=執行使用者程式碼時間/(執行使用者程式碼時間+垃圾收集時間)停頓時間越短就越適合需要與使用者互動的程式,良好的響應速度能提升使用者體驗,而高吞吐量則可用高效率地利用CPU時間,儘快完成程式的運算任務,主要適合在後臺運算而不需要太多互動的任務

Parallel Scavenge收集器提供兩個引數用於精確控制吞吐量,分別是控制最大垃圾收起停頓時間的-XX:MaxGCPauseMillis引數以及直接設定吞吐量大小的-XX:GCTimeRatio引數,arallel
Scavenge收集器還有一個引數:-XX:+UseAdaptiveSizePolicy。這是一個開關引數,當這個引數開啟後,就不需要手工指定新生代的大小(-Xmn)、Eden與Survivor區的比例(-XX:SurvivorRatio)、晉升老年代物件年齡(-XX:PretenureSizeThreshold)等細節引數,只需要把基本的記憶體資料設定好(如-Xmx設定最大堆),然後使用MaxGVPauseMillis引數或GCTimeRation引數給虛擬機器設立一個優化目標。

自適應調節策略也是Parallel Scavenge收集器與ParNew收集器的一個重要區別

4.Serial Old 收集器

Serial Old是Serial收集器的老年代版本,它同樣是一個單執行緒收集器,使用標記整理演算法。這個收集器的主要意義也是在於給Client模式下的虛擬機器使用

如果在Server模式下,主要兩大用途

(1)在JDK1.5以及之前的版本中與Parallel Scavenge收集器搭配使用

(2)作為CMS收集器的後備預案,在併發收集發生Concurrent Mode Failure(併發模式失敗)時使用

Serial Old收集器的工作工程

5.Parallel Old 收集器

Parallel Old 是Parallel Scavenge收集器的老年代版本,使用多執行緒和“標記-整理”演算法。這個收集器在1.6中才開始提供。

6.CMS收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。目前很大一部分的Java應用集中在網際網路站或者B/S系統的服務端上,這類應用尤其重視伺服器的響應速度,希望系統停頓時間最短,以給使用者帶來較好的體驗。CMS收集器就非常符合這類應用的需求。

CMS收集器是基於“標記-清除”演算法實現的。它的運作過程相對前面幾種收集器來說更復雜一些,整個過程分為4個步驟

(1)初始標記

(2)併發標記

(3)重新標記

(4)併發清除

其中,初始標記、重新標記這兩個步驟仍然需要“Stop The World”.

CMS收集器主要優點:併發收集,低停頓。

CMS三個明顯的缺點:

(1)CMS收集器對CPU資源非常敏感。CPU個數少於4個時,CMS對於使用者程式的影響就可能變得很大,為了應付這種情況,虛擬機器提供了一種稱為“增量式併發收集器”的CMS收集器變種。所做的事情和單CPU年代PC機作業系統使用搶佔式來模擬多工機制的思想

(2)CMS收集器無法處理浮動垃圾,可能出現“Concurrent Mode Failure”失敗而導致另一次Full
GC的產生。在JDK1.5的預設設定下,CMS收集器當老年代使用了68%的空間後就會被啟用,這是一個偏保守的設定,如果在應用中藍年代增長不是太快,可以適當調高參數-XX:CMSInitiatingOccupancyFraction的值來提高觸發百分比,以便降低記憶體回收次數從而獲取更好的效能,在JDK1.6中,CMS收集器的啟動閥值已經提升至92%。

(3)CMS是基於“標記-清除”演算法實現的收集器,收集結束時會有大量空間碎片產生。空間碎片過多,可能會出現老年代還有很大空間剩餘,但是無法找到足夠大的連續空間來分配當前物件,不得不提前出發FullGC。為了解決這個問題,CMS收集器提供了一個-XX:+UseCMSCompactAtFullCollection開關引數(預設就是開啟的),用於在CMS收集器頂不住要進行FullGC時開啟記憶體碎片合併整理過程,記憶體整理的過程是無法併發的,空間碎片問題沒有了,但停頓時間變長了。虛擬機器設計者還提供了另外一個引數-XX:CMSFullGCsBeforeCompaction,這個引數是用於設定執行多少次不壓縮的Full
GC後,跟著來一次帶壓縮的(預設值為0,標識每次進入Full GC時都進行碎片整理)

7. G1收集器

G1收集器的優勢:

(1)並行與併發

(2)分代收集

(3)空間整理 (標記整理演算法,複製演算法)

(4)可預測的停頓(G1處處理追求低停頓外,還能建立可預測的停頓時間模型,能讓使用者明確指定在一個長度為M毫秒的時間片段內,消耗在垃圾收集上的時間不得超過N毫秒,這幾乎已經實現Java(RTSJ)的來及收集器的特徵)

使用G1收集器時,Java堆的記憶體佈局是整個規劃為多個大小相等的獨立區域(Region),雖然還保留有新生代和老年代的概念,但新生代和老年代不再是物理隔離的了,它們都是一部分Region的集合。

G1收集器之所以能建立可預測的停頓時間模型,是因為它可以有計劃地避免在整個Java堆中進行全區域的垃圾收集。G1跟蹤各個Region裡面的垃圾堆積的價值大小(回收所獲取的空間大小以及回收所需要的時間的經驗值),在後臺維護一個優先列表,每次根據允許的收集時間,優先回收價值最大的Region(這也就是Garbage-First名稱的又來)。這種使用區域劃分記憶體空間以及有優先順序的區域回收方式,保證了G1收集器在有限的時間內可以獲取儘量可能高的回機效率

G1 記憶體“化整為零”的思路

在GC根節點的列舉範圍中加入Remembered Set即可保證不對全堆掃描也不會遺漏。

如果不計算維護Remembered Set的操作,G1收集器的運作大致可劃分為一下步驟:

(1)初始標記

(2)併發標記

(3)最終標記

(4)篩選回收

垃圾收集演算法

1)引用計數法

給物件新增引用計數器,當引用物件時計數器+1,引用失效時,計數器-1,當計數器等於0時,物件失效,記憶體可以被回收。

優點:實現簡單高效。

缺點:物件之間的互相迴圈引用問題不好解決。

2)根搜尋法

通過GC roots可達的物件路徑稱為引用鏈(reference chain),當一個物件沒有引用鏈時(即從GC roots不可達)則視為不可用物件,記憶體可以被回收。java使用該演算法進行垃圾收集

哪些物件可以視為GC roots ?

a. 虛擬機器棧中(即棧幀中的本地變數)的引用物件;

b. 本地方法棧中的引用物件;

c. 方法區(永久代)中的靜態變數引用的物件和常量池中引用的物件

垃圾回收演算法

1)複製演算法

將記憶體分為(大小相等)兩部分,每次只使用其中一塊進行記憶體分配,當記憶體使用完後,就出發GC,將存活的物件直接複製到另一塊空閒的記憶體中,然後對當前使用的記憶體塊一次性清除所有,然後轉到另一塊記憶體進行使用。
優點:簡單,高效。
缺點:浪費記憶體,因為每次都有另一塊記憶體空閒著。

2)標記-清除演算法

分兩步進行,第一步標記出可以回收的物件,第二步統一清理可以回收的物件記憶體。
缺點:首先標記和清除步驟效率都不高,其次會產生記憶體碎片。

3)標記-整理演算法

類似於標記-清除演算法,但是第二步進行記憶體回收時,將存活的物件向記憶體一端移動,達到消除記憶體碎片問題。

4)分代收集演算法

java sun hotspot虛擬機器將記憶體分為新生代(堆)、老年代(堆)、永久代(方法區、常量池、即時編譯程式碼)幾個區域,新生代主要使用基於複製演算法的垃圾回收,老年代和永久代主要使用標記-整理演算法進行垃圾回收。具體每個區域使用哪種垃圾回收演算法還要視收集器的實現制約。
這裡寫圖片描述