1. 程式人生 > >深入理解JVM——垃圾回收器(五)

深入理解JVM——垃圾回收器(五)

深入理解JVM(五)——垃圾回收器 JVM的垃圾回收主要是針對以上堆空間的垃圾回收,當然其實也會針對元資料區(永久區)進行垃圾回收。

序列收集器

使用單執行緒進行垃圾回收。 對新生代回收使用複製演算法, 對老年代使用標記壓縮演算法

最古老最穩定的收集器,回收時間較長 但其穩定性是優於其他回收器的 綜合來說是一個不錯的選擇。要使用序列收集器,可以在啟動配置時加上以下引數:

-XX:+UseSerialGC

這裡寫圖片描述 執行垃圾回收時,應用程式執行緒暫停,GC執行緒開始(開始垃圾回收),垃圾回收完成後,應用程式執行緒繼續執行。注意:在GC執行緒執行過程中使用單執行緒進行序列回收。

並行回收器

使用多執行緒並行回收 注意:針對新生代和老年代,是否都使用並行,有不同的回收器選擇:

1、 ParNew回收器

新老 並串 演算法
只針對新生代 進行併發回收 複製演算法
老年代 依然使用序列回收 標記壓縮

在多核條件下,它的效能顯然優於序列回收器,如果要使用這種回收器,可以在啟動引數中配置:

-XX:+UseParNewGC

如果要進一步指定併發的執行緒數,可以配置一下引數:

-XX:ParallelGCThreads

ParNew回收器的流程如下圖所示: 這裡寫圖片描述 在進行垃圾回收時應用程式執行緒依然被暫停,GC執行緒並行開始執行垃圾回收,垃圾回收完成後,應用程式執行緒繼續執行。

2、 Parallel回收器

兩種配置 並串 區別 在啟動程式中配置
似於ParNEW 新生代使用並行回收、老年代使用序列回收 區別:設計目標上更重視吞吐量,相同的條件下它比ParNew更優 -XX:+UseParallelGC
不同於ParNew 對於新生代和老年代均適應並行回收 —— XX:+UseParallelOldGC

Parallel回收器的流程和ParNew的流程是一致的:

CMS回收器

Concurrent Mark Sweep,併發標記清除。【是一種針對老年代的回收器,不對新生代產生作用】

併發 , 可以與應用程式併發執行、交替執行 標記清除,前面介紹的序列回收器和併發回收器,使用的是標記壓縮演算法。

優點在於減少了應用程式停頓的時間,因為它不需要應用程式完成暫定等待垃圾回收,而是與垃圾回收併發執行。要執行這種垃圾回收器可以在啟動引數中配置:

-XX:+UseConcMarkSweepGC

CMS回收機執行機制非常複雜,我們簡單的將他的執行流程分為以下幾步:

初始標記:標記從GC Root可以直接可達的物件; 併發標記(和應用程式執行緒一起):主要標記過程,標記全部物件;標記過程是併發執行的,可以與應用程式執行緒同時進行 重新標記:由於併發標記時,使用者執行緒依然執行,因此在正式清理前,再做依次重新標記,進行修正。 併發清除(和使用者執行緒一起):基於標記結果,直接清理物件。

流程如下圖所示:

併發標記:標記過程是併發執行的,可以與應用程式執行緒同時進行 初始標記和重新標記 不能和應用程式併發執行,但這兩個過程標記速度快,時間短,所以對應用程式不會產生太大的影響 併發清除,和應用程式同時進行,避免了應用程式的停頓。

CMS的優點顯而易見,就是減少了應用程式的停頓時間,讓回收執行緒和應用程式執行緒可以併發執行。 但它也不是完美的,從他的執行機制可以看出,因為它不像其他回收器一樣集中一段時間對垃圾進行回收,並且在回收時應用程式還是執行,因此它的回收並不徹底。這也導致了CMS回收的頻率相較其他回收器要高,頻繁的回收將影響應用程式的吞吐量。

G1回收器

G1回收器是jdk1.7以後推出的回收器,試圖取代CMS回收器。

不同於其他的回收器、G1將堆空間劃分成了互相獨立的區塊。每塊區域既有可能屬於老年代、也有可能是新生代,並且每類區域空間可以是不連續的(對比CMS的老年代和新生代都必須是連續的)。這種將老年代區劃分成多塊的理念源於:當併發後臺執行緒尋找可回收的物件時、有些區塊包含可回收的物件要比其他區塊多很多。雖然在清理這些區塊時G1仍然需要暫停應用執行緒、但可以用相對較少的時間優先回收包含垃圾最多區塊。這也是為什麼G1命名為Garbage First的原因:第一時間處理垃圾最多的區塊。

要使用G1回收器需要在啟動是配置以下引數:

-XX:+UseG1GC

G1相對CMS回收器來說優點在於:

1、因為劃分了很多區塊,回收時減小了記憶體碎片的產生; 2、G1適用於新生代和老年代,而CMS只適用於老年代。

小結

本文簡要介紹了JVM中的垃圾回收器,主要包括序列回收器、並行回收器以及CMS回收器、G1回收器。他們各自都有優缺點,通常來說你需要根據你的業務,進行基於垃圾回收器的效能測試,然後再做選擇。下面給出配置回收器時,經常使用的引數:

-XX:+UseSerialGC:在新生代和老年代使用序列收集器

-XX:+UseParNewGC:在新生代使用並行收集器

-XX:+UseParallelGC :新生代使用並行回收收集器,更加關注吞吐量

-XX:+UseParallelOldGC:老年代使用並行回收收集器

-XX:ParallelGCThreads:設定用於垃圾回收的執行緒數

-XX:+UseConcMarkSweepGC:新生代使用並行收集器,老年代使用CMS+序列收集器

-XX:ParallelCMSThreads:設定CMS的執行緒數量

-XX:+UseG1GC:啟用G1垃圾回收器