預計閱讀時間: 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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。