- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- java中的串行并行及CMS垃圾回收器是怎樣的
本篇文章給大家分享的是有關(guān)java中的串行并行及CMS垃圾回收器是怎樣的,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習,希望大家閱讀完這篇文章后可以有所收獲,話(huà)不多說(shuō),跟著(zhù)小編一起來(lái)看看吧。
SerialGC
串行回收器是指使用單線(xiàn)程的回收器。每次回收器,串行回收器只有一個(gè)工作線(xiàn)程,對于并行能力較弱的計算機來(lái)說(shuō),串行回收器的專(zhuān)注性和獨占性往往能讓其有更好的性能表現。
串行回收器可以在新生代和老年代使用,根據不同的堆空間分為新生代串行回收器和老年代串行器。
SerialGC
串行回收器主要有兩個(gè)特點(diǎn):
僅僅使用單線(xiàn)程進(jìn)行垃圾回收
獨占式的垃圾回收方式
使用 -XX:+UseSerialGC
參數可以指定使用新生代串行回收器或老年代串行回收器。當虛擬機在Client模式下運行時(shí),它是默認的垃圾回收器。
SerialOldGC
老年代串行回收器使用的標記壓縮法,和新生代串行回收器一樣,它也是一個(gè)串行的獨占式的垃圾回收器。由于老年代垃圾回收通常會(huì )需要比新生代垃圾回收更長(cháng)的時(shí)間,在堆空間較大的應用程序中,一旦老年代串行回收器啟動(dòng),應用程序很可能會(huì )停頓較長(cháng)的時(shí)間。
若要開(kāi)啟老年代串行回收器,可以嘗試使用以下參數
-XX:+UseSerialGC
:新生代老年代都使用串行回收器
-XX:+UseParNewGc
:新生代使用parNew回收器,老年代使用串行回收器,jdk9、jdk10已刪除該參數,因為ParNew需要和CMS搭配工作,而CMS已經(jīng)被G1替代,不再支持此參數。
-XX:+UseParallelGC
:新生代使用ParallelGC回收器,老年代使用串行回收器。
示例代碼:
public class Demo02 { public static void main(String[] args) { byte[] b = null; for(int i = 0; i < 10; i++) { b = new byte[2 * 1024 * 1024]; } } }
使用參數 -Xmx10m -Xms10m -Xmn2m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC
運行,gc 日志如下:
//回收新生代 [GC (Allocation Failure) [DefNew: 1024K->337K(1536K), 0.0007683 secs] 1024K->337K(9728K), 0.0007883 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] //回收新生代與老年代 [GC (Allocation Failure) [DefNew: 645K->37K(1536K), 0.0008160 secs][Tenured: 6470K->2410K(8192K), 0.0015724 secs] 6789K->2410K(9728K), [Metaspace: 2952K->2952K(1056768K)], 0.0024163 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] // 省略其他日志...
日志中的 DefNew
表示新生代,Tenured
表示老年代。
并行回收器在串行回收器的基礎上做了改進(jìn),它使用了多個(gè)線(xiàn)程同時(shí)進(jìn)行垃圾回收。對于并行能力強的計算機,可以有效減少垃圾回收所需要的時(shí)間。
SerialGC
的多線(xiàn)程版本:ParNew
回收器ParNew
回收器是一個(gè)工作在新生代的垃圾回收器。
它只是簡(jiǎn)單地將串行回收器多線(xiàn)程化,它的回收策略、算法及參數和新生代串行回收器一樣。在并發(fā)能力比較強的cpu上,它產(chǎn)生的停頓時(shí)間要短于串行回收器,而單cpu或者并發(fā)能力較弱的系統中,并行回收器的效果不會(huì )比串行回收器好,由于多線(xiàn)程的壓力,它的實(shí)際表現很可能比串行回收器差。
開(kāi)啟 ParNew
回收器可以使用以下參數:
-XX:+UseParNewGC
:新生代使用ParNew回收器,老年代使用串行回收器。jdk9、jdk10中已經(jīng)刪除,因為ParNew需要和CMS搭配工作,而CMS已經(jīng)被G1替代,不再支持此參數。
-XX:+UseConcMarkSweepGC
:新生代使用ParNew回收器,老年代使用CMS.jdk9、jdk10中不建議使用,建議使用默認的G1垃圾回收器。
ParNew回收器工作時(shí)的線(xiàn)程數可以使用-XX:ParallelGCThreads
參數指定。一般,最好與CPU數量相當,避免過(guò)多的線(xiàn)程數影響垃圾回收性能。在默認情況下,當CPU數量小于8時(shí),ParallelGCThreads
的值等于CPU數量,當CPU數量大于8時(shí),ParallelGCThreads
的值等于3+((5xCPU_Count)/8)
(CPU數量為16時(shí),ParallelGCThreads
的值為13)
示例代碼:
public class Demo02 { public static void main(String[] args) { byte[] b = null; for(int i = 0; i < 10; i++) { b = new byte[2 * 1024 * 1024]; } } }
使用參數 -Xmx10m -Xms10m -Xmn2m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseParNewGC
運行,gc 日志如下:
[GC (Allocation Failure) [ParNew: 1024K->384K(1536K), 0.0004642 secs] 1024K->384K(9728K), 0.0004796 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [ParNew: 691K->265K(1536K), 0.0009477 secs][Tenured: 6509K->2407K(8192K), 0.0012491 secs] 6835K->2407K(9728K), [Metaspace: 2933K->2933K(1056768K)], 0.0022175 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [ParNew: 41K->45K(1536K), 0.0006914 secs][Tenured: 6503K->2407K(8192K), 0.0012305 secs] 6544K->2407K(9728K), [Metaspace: 2936K->2936K(1056768K)], 0.0019425 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] // 省略其他日志...
可以看到,這個(gè)輸出和新生代串行回收器的輸出幾乎一致,只有回收器標識符不同。
ParallelGC
ParallelGC
是一個(gè)既可以工作在新生代,又可以工作在老年代的垃圾回收器。工作在新生代時(shí),叫ParallelGC
,工作在老年代時(shí)叫ParallelOldGC
ParallelGC
回收器新生代 ParallelGC
回收器也是使用復制算法的回收器。從表面上看,它和ParaNew
回收器一樣,都是多線(xiàn)程、獨占式的回收器,但是Parallel回收器有一個(gè)重要的特點(diǎn):它非常關(guān)注系統的吞吐量。
新生代Parallel
回收器可以使用以下參數啟用:
-XX:+UseParallelGC
:新生代使用ParallelGC
回收器,老年代使用串行回收器。
-XX:+UseParallelOldGC
:新生代使用ParallelGC
回收器,老年代使用ParallelOldGC
回收器。
ParallelGC
回收器提供了兩個(gè)重要的參數用于控制系統的吞吐量:
-XX:MaxGCPauseMillis
:設置最大垃圾回收停頓時(shí)間。它的值是一個(gè)大于0的整數。ParallelGC
在工作時(shí),會(huì )調整java堆大小或者其他參數,盡可能指導停頓時(shí)間控制在MaxGCPauseMillis
以?xún)取?/p>
-XX:GCTimeRatio
:設置吞吐量大小。它的值是一個(gè)0到100之間的整數,假設GCTimeRation
的值為n,那么系統將花費不超過(guò)1/(1+n)
的時(shí)間進(jìn)行垃圾回收,默認情況下它的取值是99,即有不超過(guò)1/(1+99)=1%
的時(shí)間用于垃圾回收。
除此之外,ParallelGC
回收器還支持一種自適應的GC調節策略,使用-XX:+UseAdaptiveSizePolicy
可以打開(kāi)自適應策略。在這種模式下,新生代的大小、eden區和survivor區的比例、晉升老年代的對象年齡等參數會(huì )被自動(dòng)調整,以達到堆大小、吞吐量和停頓時(shí)間之間的平衡點(diǎn)。
ParallelOldGC
回收器老年代ParallelOldGC
回收器也是一種多線(xiàn)程并發(fā)的回收器。和新生代ParallelGC
回收器一樣,它也是一種關(guān)注吞吐量的回收器。
老年代ParallelOldGC
可以使用以下參數啟用:
-XX:+UseParallelOldGC
:新生代使用ParallelGC
回收器,老年代使用ParallelOldGC
回收器。
參數 -XX:ParallelGCThreads
也可以用于設置垃圾回收時(shí)的線(xiàn)程數量。
示例代碼:
public class Demo02 { public static void main(String[] args) { byte[] b = null; for(int i = 0; i < 10; i++) { b = new byte[2 * 1024 * 1024]; } } }
使用參數 -Xmx10m -Xms10m -Xmn2m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseParallelOldGC
運行,gc 日志如下:
//回收年輕代 [GC (Allocation Failure) [PSYoungGen: 464K->432K(1536K)] 6616K->6584K(9728K), 0.0013387 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] //回收老年代 [Full GC (Allocation Failure) [PSYoungGen: 432K->0K(1536K)] [ParOldGen: 6152K->2407K(8192K)] 6584K->2407K(9728K), [Metaspace: 2928K->2928K(1056768K)], 0.0032880 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
與 ParallelGC
和 ParallelOldGC
不同,CMS (Concurrent Mark Sweep
,意為并發(fā)標記清除) 回收器主要關(guān)注系統停頓時(shí)間。它是一個(gè)老年代垃圾回收器。
CMS主要工作步驟如下:
初始標記(CMS-initial-mark
):標記根對象(STW)
并發(fā)標記(CMS-concurrent-mark
):標記所有對象
預清理(MS-concurrent-preclean
):清理前準備及控制停頓時(shí)間
重新標記(CMS-remark
):修正并發(fā)標記數據(STW)
并發(fā)清理(CMS-concurrent-sweep
):清理垃圾
并發(fā)重置(CMS-concurrent-reset
):垃圾回收完成后,重新初始化CMS數據,為下一次垃圾回收做準備。
以上過(guò)程中,并發(fā)標記、并發(fā)清理和并發(fā)重置都是可以和應用線(xiàn)程一起執行的。
CMS
回收器的主要參數如下:
啟動(dòng)CMS
垃圾回收器:-XX:+UseConcMarkSweepGC
關(guān)閉預清理:-XX:-CMSPrecleaningEnabled
。在整個(gè)CMS的回收過(guò)程中,默認情況下,在并發(fā)標記之后,會(huì )有一個(gè)預清理的操作,預清理是并發(fā)的,除了為正式清理做準備檢查,還會(huì )嘗試控制一次停頓時(shí)間。
設置CMS的并發(fā)線(xiàn)程數:CMS默認啟動(dòng)的回收線(xiàn)程數目是 (ParallelGCThreads + 3)/4)
,如果你需要明確設定,可以通過(guò)-XX:ParallelCMSThreads=20
來(lái)設定,其中ParallelGCThreads
是年輕代的并行收集線(xiàn)程數.
指定內存回收的閾值:由于CMS
不是獨占式的,在回收過(guò)程中,應用程序仍然在不停地工作。在應用程序工作的過(guò)程中,又會(huì )不斷地產(chǎn)生垃圾,這些新垃圾在當前的回收過(guò)程中是無(wú)法清除的。同時(shí),因為應用程序沒(méi)有中斷,所以在CMS回收過(guò)程中,還應該確保應用程序有足夠的內存可用。因此,CMS回收器不會(huì )等到堆內存飽和時(shí)才進(jìn)行垃圾回收,而當堆內存使用率達到某一閾值時(shí)便開(kāi)始進(jìn)行回收。這個(gè)回收閾值可以通過(guò)參數-XX:CMSInitiatingOccupancyFraction
指定,默認是68,即老年代空間使用率達到68%時(shí),會(huì )執行一次CMS回收。
開(kāi)啟碎片整理:CMS是不會(huì )整理堆碎片的,因此為了防止堆碎片引起full gc
,通過(guò)會(huì )開(kāi)啟CMS階段進(jìn)行合并碎片選項:-XX:+UseCMSCompactAtFullCollection
,內存碎片的整理不是并發(fā)進(jìn)行的,因此性能上會(huì )有所消耗。
指定多少次CMS回收后,進(jìn)行一次內存壓縮:-XX:CMSFullGCBeforeCompaction
回收Perm
區:CMS默認不回收Perm
區的,如果Perm
區滿(mǎn)了,會(huì )觸發(fā)一次FullGC。如果希望使用CMS回收Perm區,可以使用參數-XX:+CMSClassUnloadingEnabled
。
示例代碼:
public class Demo02 { public static void main(String[] args) { byte[] b = null; for(int i = 0; i < 10; i++) { b = new byte[2 * 1024 * 1024]; } } }
使用參數 -Xmx10m -Xms10m -Xmn2m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC
運行,gc 日志如下:
[GC (Allocation Failure) [ParNew: 1024K->362K(1536K), 0.0013608 secs] 1024K->362K(9728K), 0.0014303 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [ParNew: 730K->264K(1536K), 0.0028882 secs][CMS: 6490K->2418K(8192K), 0.0025366 secs] 6874K->2418K(9728K), [Metaspace: 3008K->3008K(1056768K)], 0.0054949 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] [GC (CMS Initial Mark) [1 CMS-initial-mark: 4466K(8192K)] 4466K(9728K), 0.0004792 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-mark-start] [GC (Allocation Failure) [ParNew: 41K->55K(1536K), 0.0008476 secs][CMS[CMS-concurrent-mark: 0.002/0.003 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] (concurrent mode failure): 6514K->2418K(8192K), 0.0035573 secs] 6555K->2418K(9728K), [Metaspace: 3016K->3016K(1056768K)], 0.0044327 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] [GC (Allocation Failure) [ParNew: 41K->11K(1536K), 0.0008080 secs][CMS: 6514K->2419K(8192K), 0.0013165 secs] 6555K->2419K(9728K), [Metaspace: 3026K->3026K(1056768K)], 0.0021484 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] [GC (CMS Initial Mark) [1 CMS-initial-mark: 4467K(8192K)] 4467K(9728K), 0.0002437 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-mark-start] [GC (Allocation Failure) [ParNew: 20K->4K(1536K), 0.0006944 secs][CMS[CMS-concurrent-mark: 0.001/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] (concurrent mode failure): 6515K->2419K(8192K), 0.0023357 secs] 6536K->2419K(9728K), [Metaspace: 3037K->3037K(1056768K)], 0.0030568 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
相關(guān)信息說(shuō)明如下:
CMS Initial Mark
:初始標記
CMS-concurrent-mark
:并發(fā)標記
CMS-concurrent-preclean-start
:預清理
CMS-concurrent-abortable-preclean
: 可中止的預清理,等待一次新生代GC再進(jìn)行后續操作。預清理后是重新標記階段,由于重新標記是獨占CPU的,如果新生代GC發(fā)生后,立即觸發(fā)一次重新標記,那么一次停頓的時(shí)間可能會(huì )很長(cháng),為了避免這種情況,預處理會(huì )刻意等待一次新生代GC的發(fā)生,然后根據歷史性能數據預測下一次新生代GC可能發(fā)生的時(shí)間,在當前時(shí)間和預測時(shí)間的中間時(shí)刻進(jìn)行重新標記,這樣盡量避免新生代GC和重新標記重合,盡可能減少一次停頓時(shí)間。
CMS-remark
:重新標記
CMS-concurrent-sweep
:并發(fā)清除
CMS-concurrent-reset
:并發(fā)重置
concurrent mode failure
:CMS回收器并發(fā)回收失敗,這很可能是應用程序在運行過(guò)程中,垃圾未回收完成而新垃圾又在產(chǎn)生,導致老年代空間不夠造成的,可以考慮增加老年代空間,或者設置一個(gè)較小的-XX:CMSInitiatingOccupancyFraction
參數。注意:如果在CMS的執行過(guò)程中,已經(jīng)出現了內存不足的情況,CMS回收就會(huì )失敗,虛擬機將啟動(dòng)老年代串行回收器進(jìn)行垃圾回收,此時(shí)應用程序將完全中斷,直到垃圾回收完成,因此應盡量避免這種情況發(fā)生。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站