深入理解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垃圾回收器