Java之JVM的深刻探究(五)--垃圾回收器

預計閱讀時間: 9分鐘java


    咱們在上一篇中已經詳細的探究了關於JVM的垃圾回收的幾種算法,從中咱們知道了不一樣的算法有這不一樣的優缺點的,然而實際在Java的JVM的並非單純的使用其中的某一種算法來實現垃圾回收的,而是將不一樣的垃圾回收算法包裝在不一樣的垃圾回收器當中,這樣用戶就能夠根據自身的需求,有選擇性的使用不一樣的垃圾回收器,以便讓本身的java程序性能到達最佳。算法

垃圾回收器概述:垃圾收集器是垃圾回收算法(標記-清除算法、複製算法、標記-整理算法、分代收集算法等)的具體實現,不一樣商家、不一樣版本的JVM所提供的垃圾收集器可能會有很在差異,本文主要介紹HotSpot虛擬機中的垃圾收集器。微信


在探究垃圾回收器以前咱們先來回憶下以前探究過的關於JVM內存模型中的Java堆的知識,先來看一下Java堆的結構圖以下:多線程

java堆內存結構包括:新生代和老年代,其中新生代由一個伊甸區和2個倖存區組成,2個倖存區是大小相同,徹底對稱的,沒有任何差異。咱們把它們稱爲S0區和S1區,也能夠稱爲from區和to區。併發


JVM的垃圾回收主要是針對以上堆空間的垃圾回收,固然其實也會針對元數據區(永久區)進行垃圾回收,在此咱們主要針對堆內存空間的垃圾回收進行探究。性能

垃圾收集器組合:spa


下面咱們介紹幾種常見的垃圾回收器:
.net


一、>>串行收集器:線程

(1)特色: 
  –它僅僅使用單線程進行垃圾回收 
  –它是獨佔式的垃圾回收 
  –進行垃圾回收時, Java應用程序中的線程都須要暫停(Stop-The-World) 
  –適合CPU等硬件不是很好的場合設計

       –對新生代的回收使用複製算法,對老年代使用標記壓縮算法,這也和以前介紹的垃圾回收算法優點是相合拍的 

       –是最古老最穩定的收集器,儘管它是串行回收,回收時間較長,但其穩定性是優於其餘回收器的,綜合來講是一個不錯的選擇。  

(2)設置參數: 
  -XX:+UseSerialGC 指定新生使用新生代串行收集器和老年代串行收集器, 當以client模式運行時, 它是默認的垃圾收集器

串行回收器的執行流程以下所示:


二、>>並行回收器:

顧名思義,並行回收器就是使用多線程並行回收,不過這裏須要注意的是,針對新生代和老年代,是否都使用並行,有不一樣的回收器選擇:


2.一、 ParNew回收器:

(1)特色: 
  –這個回收器只針對新生代進行併發回收,老年代依然使用串行回收 
  –回收算法依然和串行回收同樣,新生代使用複製算法,老年代使用標記壓縮算法
  –垃圾回收時, 應用程序仍會暫停, 只不過因爲是多線程回收, 在多核CPU上,回收效率會高於串行回收器, 反之在單核CPU, 效率會不如串行回收器 
(2)設置參數: 

        -XX:+UseParNewGC  若是要進一步指定併發的線程數,能夠配置一下參數:

        -XX:ParallelGCThreads

串行回收器的執行流程以下所示:


2.二、Parallel回收器:

依然是並行回收器,但這種回收器有兩種配置

一種相似於ParNEW:

(1)特色: 
  –新生代使用並行回收、老年代使用串行回收 
  –它與ParNew的不一樣在於它在設計目標上更重視吞吐量 
  –能夠認爲在相同的條件下它比ParNew更優。 
(2)設置參數: 

        -XX:+UseParallelGC

另一種配置則不一樣於ParNew:

(1)特色: 
  –對於新生代和老年代均適應並行回收  
(2)設置參數: 

        -XX:+UseParallelOldGC

Parallel回收器的流程和ParNew的流程是一致的,以下圖:


三、>>CMS回收器(Concurrent Mark Sweep,併發\標記清除):

CMS回收器: Concurrent Mark Sweep,併發標記清除。注意這裏注意兩個詞:併發、標記清除。

(1)特色: 
  –是能夠與應用程序併發執行、交替執行, 非獨佔式的回收器, 大部分時候應用程序不會中止運行 
  –是一種針對老年代的回收器,不對新生代產生做用 
  –標記清除表示這種回收器不是使用的是標記整理算法,這和前面介紹的串行回收器和併發回收器有所不一樣, 所以回收後會有內存碎片, 可使參數設置進行內存碎片的壓縮整理  

       –與ParallelGC和ParallelOldGC不一樣, CMS主要關注系統停頓時間 ,這種回收器優勢在於減小了應用程序停頓的時間,由於它不須要應用程序完成暫定等待垃圾回收,而是與垃圾回收併發執行。

(2)CMS主要步驟: 
  1. 初始標記 :標記從GC Root能夠直接可達的對象;

  2. 併發標記(應用程序線程一塊兒) :主要標記過程,標記所有對象;

  3. 預清理 
  4. 從新標記 :因爲併發標記時,用戶線程依然運行,所以在正式清理前,再作依次從新標記,進行修正。

  5. 併發清理(用戶線程一塊兒) :基於標記結果,直接清理對象。

  6. 併發重置

–>注:初始標記與理新標記是獨佔系統資源的,不能與用戶線程一塊兒執行,而其它階段則能夠與用戶線程一塊兒執行 
(3)設置參數: 
  -XX:+UseConcMarkSweepGC 老年代使用CMS回收器, 新生代使用ParNew回收器 

流程以下圖所示:


注:初始標記與從新標記是獨佔系統資源的,不能與用戶線程一塊兒執行,而其它階段則能夠與用戶線程一塊兒執行 。

從上圖能夠看到標記過程分三步:初始標記、併發標記、從新標記。併發標記是最主要的標記過程,而這個過程是併發執行的,能夠與應用程序線程同時進行,初始標記和從新標記雖然不能和應用程序併發執行,但這兩個過程標記速度快,時間短,因此對應用程序不會產生太大的影響。最後併發清除的過程,也是和應用程序同時進行的,避免了應用程序的停頓。


CMS的優缺點:

優勢:就是減小了應用程序的停頓時間,讓回收線程和應用程序線程能夠併發執行。但它也不是完美的,

缺點:從他的運行機制能夠看出,由於它不像其餘回收器同樣集中一段時間對垃圾進行回收,而且在回收時應用程序仍是運行,所以它的回收並不完全。這也致使了CMS回收的頻率相較其餘回收器要高,頻繁的回收將影響應用程序的吞吐量。


四、>>G1回收器(jdk1.7後全新的回收器, 試圖用於取代CMS):

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

不一樣於其餘的回收器、G1將堆空間劃分紅了互相獨立的區塊。每塊區域既有可能屬於老年代、也有多是新生代,而且每類區域空間能夠是不連續的(對比CMS的老年代和新生代都必須是連續的)。這種將老年代區劃分紅多塊的理念源於:當併發後臺線程尋找可回收的對象時、有些區塊包含可回收的對象要比其餘區塊多不少。雖然在清理這些區塊時G1仍然須要暫停應用線程、但能夠用相對較少的時間優先回收包含垃圾最多區塊。這也是爲何G1命名爲Garbage First的緣由:第一時間處理垃圾最多的區塊。


(1)特色: 
  –獨特的垃圾回收策略, 屬於分代垃圾回收器
  –使用分區算法, 不要求eden, 年輕代或老年代的空間都連續 
  –並行性: 回收期間, 可由多個線程同時工做, 有效利用多核cpu資源 
  –併發性: 與應用程序可交替執行, 部分工做能夠和應用程序同時執行, 
  –分代GC: 分代收集器, 同時兼顧年輕代和老年代 
  –空間整理: 回收過程當中, 會進行適當對象移動, 減小空間碎片 
  –可預見性: G1可選取部分區域進行回收, 能夠縮小回收範圍, 減小全局停頓 
(2)設置參數: 
  -XX:+UseG1GC  打開G1收集器開關, 

G1相對CMS回收器來講主要優勢在於:

一、由於劃分了不少區塊,回收時減少了內存碎片的產生;

二、G1適用於新生代和老年代,而CMS只適用於老年代。


到此,JVM垃圾回收器的探究已完畢,下面列出這些常使用的垃圾回收器配置參數的快照:

-XX:+UseSerialGC

在新生代和老年代使用串行收集器

-XX:+UseParNewGC

在新生代使用並行收集器

-XX:+UseParallelGC

新生代使用並行回收收集器,更加關注吞吐量

-XX:+UseParallelOldGC

老年代使用並行回收收集器

-XX:ParallelGCThreads

設置用於垃圾回收的線程數

-XX:+UseConcMarkSweepGC

新生代使用並行收集器,老年代使用CMS+串行收集器

-XX:ParallelCMSThreads

設定CMS的線程數量

-XX:+UseG1GC

啓用G1垃圾回收器


更多技術文章,掃描下方二維碼關注我!!!


本文分享自微信公衆號 - 一隻藍色猿(umizhang0910)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索