国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

四、GC算法實現(xiàn)

2019-11-06 06:25:08
字體:
供稿:網(wǎng)友

  在了解了上一章中GC算法的基本概念之后,本章將深入到各GC算法的具體實現(xiàn)中。對大多數(shù)JVM來說,一般需要選擇兩種GC算法,一種用于回收新生代內(nèi)存區(qū),另一種用于回收老年代內(nèi)存區(qū)域。

  新生代和老年代GC算法的可能組合如下表所示,如果不指定的話,將會在新生代和老年代中選擇默認的GC算法。下表中的GC算法組合是基于java 8的,在其他Java版本中可能會有所不同。

新生代GC算法 老年代GC算法 JVM參數(shù)
Incremental Incremental -Xincgc
Serial Serial -XX:+UseSerialGC
Parallel Scavenge Serial -XX:+UseParallelGC -XX:+UseParallelOldGC
Parallel New Serial N/A
Serial Parallel Old N/A
Parallel Scavenge Parallel Old -XX:+UseParallelGC -XX:+UseParallelOldGC
Parallel New Parallel Old N/A
Serial CMS -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
Parallel Scavenge CMS N/A
Parallel New CMS -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
G1 -XX:+UseG1GC

     如果現(xiàn)在覺得上表看起來覺得很復(fù)雜,請別著急。一般常用的是上面加粗的四種組合。剩下的組合一般是已經(jīng)不用了,或者是不再支持,或者在實際中基本不使用。所以,在接下來的文章中,只介紹上面這四種組合。

新生代和老年代的串行GC(Serial GC)新生代和老年代的并行GC(Parallel GC)新生代并行GC(Parallel GC) + 老年代CMS部分新生代老年代的G1

一、串行GC(Serial GC)

  串行GC對于新生代使用標記復(fù)制(mark-copy)策略,對老年代使用標記清除整理(mark-sweep-compact)策略進行垃圾回收。這些收集器是單線程的,不能并發(fā)的對垃圾進行回收。并且在垃圾回收動作時會暫停整個應(yīng)用線程(stop-the-world)。

  這種GC算法無法充分利用硬件資源,即使有多個核,在GC時也只用其中一個。在新生代和老年代啟動串行GC的命令如下:

java -XX:+UseSerialGC com.mypackages.MyExecutableClass

  這種GC算法一般并不常用,只有在堆內(nèi)存為幾百MB,并且應(yīng)用運行在單核CPU上時才使用。一般應(yīng)用都部署在多核的服務(wù)器上,如果使用串行GC會在GC時無法充分利用資源,造成性能瓶頸,提高應(yīng)用延遲和降低吞吐量。

  接下來我們看一個串行GC的垃圾收集日志信息,使用如下命令使應(yīng)用打印出GC日志,

-XX:+PRingGCDetails -XX:+PringGCDateStamps -XX:+PringGCTimeStamps

  輸出日志如下,

2015-05-26T14:45:37.987-0200: 151.126: [GC (Allocation Failure) 151.126: [DefNew:629119K->69888K(629120K), 0.0584157 secs] 1619346K->1273247K(2027264K), 0.0585007 secs][Times: user=0.06 sys=0.00, real=0.06 secs]2015-05-26T14:45:59.690-0200: 172.829: [GC (Allocation Failure) 172.829: [DefNew:629120K->629120K(629120K), 0.0000372 secs]172.829: [Tenured: 1203359K->755802K(1398144K), 0.1855567 secs] 1832479K->755802K(2027264K), [Metaspace:6741K->6741K(1056768K)], 0.1856954 secs] [Times: user=0.18 sys=0.00, real=0.18 secs]

  從上面這段日志信息中可以看到進行了兩次GC,第一次清理了新生代,第二次清理了新生代和老年代空間。

1、Minor GC

  清理新生代內(nèi)存的GC事件日志如下,

2015-05-26T14:45:37.987-02001 : 151.12622 : [ GC3 (Allocation Failure4 151.126: [DefNew5 : 629119K->69888K6 (629120K)7> , 0.0584157 secs] 1619346K-1273247K8 (2027264K)9, 0.0585007> secs10] [Times: user=0.06 sys=0.00, real=0.06 secs]11

     對照上面的不同字段進行說明, (1)2015-05-26T14:45:37.987-0200,發(fā)生本次GC動作的時間 (2)151.126,GC事件發(fā)生時距離該JVM啟動的時間,單位為秒 (3)GC,用于區(qū)分是Minor GC還是Full GC。這里表示本次是Minor GC (4)Allocation Failure,導(dǎo)致本次進行GC的原因。在這里,本次GC是由于無法為新的數(shù)據(jù)結(jié)構(gòu)在新生代中分配內(nèi)存空間導(dǎo)致的。 (5)DefNew,垃圾收集器的名稱。這個名稱表示的是在新生代中進行的單線程,標記-復(fù)制,全應(yīng)用暫停的垃圾收集器 (6)629119K->69888K,表示新生代內(nèi)存空間在GC前后的大小。 (7)629120K,表示新生代的總大小 (8)1619346K->1273247K,堆內(nèi)存在GC前后的大小 (9)2027264K,堆內(nèi)存中可用大小 (10)0.0585007 secs,GC動作的時間,單位為秒 (11)Times: user=0.06 sys=0.00, real=0.06 secs,GC動作的時間,其中

user- 表示在此次垃圾回收過程中,所有GC線程消耗的CPU時間之和sys - 表示GC過程中操作系統(tǒng)調(diào)用和系統(tǒng)等等事件所消耗的時間

real - 應(yīng)用暫停的總時間。由于串行GC是單線程的,所以暫停總時間等于user時間和sys時間之和      經(jīng)過上面這些分析后,我們可以更加清楚的從GC日志中獲取到當(dāng)時的詳細信息。在GC前,總共使用了1619346K堆內(nèi)存,其中新生代使用了629119K。通過計算就可以得到老年代使用了990227K。

  GC后,新生代釋放出了559231K內(nèi)存空間,但是堆的總內(nèi)存僅僅釋放了346099K。也就是說,在本次GC時,有213132K的對象從新生代升級到了老年代區(qū)域。

  下圖形象的表明了本次GC前后內(nèi)存的變化情況。   這里寫圖片描述   

2、Full GC

  理解了Minor GC事件后,接下來我們看一下第二次GC的日志,

2015-05-26T14:45:59.690-02001 : 172.8292 : [GC (Allocation Failure 172.829: [DefNew: 629120K->629120K(629120K), 0.0000372 secs3] 172.829:[Tenured4: 1203359K->755802K5 (1398144K)6, 0.1855567 secs7 ] 1832479K->755802K8 (2027264K)9, [Metaspace: 6741K->6741K(1056768K)]10[Times: user=0.18 sys=0.00, real=0.18 secs]11

     對上面各組數(shù)據(jù)進行分析, (1)2015-05-26T14:45:59.690-0200,本次GC事件發(fā)生的時間 (2)172.829,GC時JVM的啟動總時間,單位為秒。 (3)[DefNew: 629120K->629120K(629120K), 0.0000372 secs,由于分配內(nèi)存不足導(dǎo)致的一次新生代GC。在本次GC時,首先進行的是新生代的DefNew類型GC,將新生代的內(nèi)存使用從629120K降低到0。注意在這里,JVM的顯示有問題,誤認為年輕代內(nèi)存使用完了。本次GC耗時0.0000372秒 (4)Tenured,老年代垃圾收集器的名稱。Tenured表示一個單線程,暫停整個應(yīng)用線程的標記清除整理的垃圾收集過程。 (5)1203359K->755802K,老年代在垃圾回收前后的內(nèi)存使用情況 (6)1398144K,老年代總內(nèi)存數(shù) (7)0.1855567 secs,老年代垃圾回收的耗時 (8)1832479K->755802K,垃圾回收前后總堆內(nèi)存的變化情況(包括新生代和老年代) (9)2027264K,JVM堆的可用內(nèi)存 (10)[Metaspace: 6741K->6741K(1056768K)],元數(shù)據(jù)區(qū)在垃圾回收前后的內(nèi)存使用情況,從這里可以看出,本次GC時并沒有對元數(shù)據(jù)區(qū)的內(nèi)存進行回收 (11)[Times: user=0.18 sys=0.00, real=0.18 secs],GC事件的耗時,

user- 表示在此次垃圾回收過程中,所有GC線程消耗的CPU時間之和sys - 表示GC過程中操作系統(tǒng)調(diào)用和系統(tǒng)等等事件所消耗的時間real - 應(yīng)用暫停的總時間。由于串行GC是單線程的,所以暫停總時間等于user時間和sys時間之和      本次Full GC與上面的Minor GC區(qū)別十分明顯,F(xiàn)ull GC是會對老年代和元數(shù)據(jù)區(qū)進行垃圾回收的。本次垃圾回收的過程如下圖所示,      這里寫圖片描述   

二、并行GC(Parallel GC)

  在這種GC模式下,新生代使用標記復(fù)制策略,老年代使用標記清除整理策略。新生代和老年代的GC事件都會導(dǎo)致所有應(yīng)用線程暫停。新生代和老年代在復(fù)制(copy)或整理(compact)階段都使用多線程,這也是并行GC名稱的來由。使用這種GC算法,可以降低垃圾回收的時間消耗。      在垃圾回收時的并行線程數(shù),可以由參數(shù)-XX:+ParallelGCThreads=NNN來設(shè)置。該參數(shù)的默認值是服務(wù)器的核數(shù)。      使用并行GC,可以用以下三種命令模式:

java -XX:+UseParallelGC com.mypackages.MyExecutableClassjava -XX:+UseParallelOldGC com.mypackages.MyExecutableClassjava -XX:+UseParallelGC -XX:+UseParallelOldGC com.mypackages.MyExecutableClass

     并行垃圾收集器一般用在多核服務(wù)器上,在多核服務(wù)器上使用并行GC,能重復(fù)利用硬件資源,提高應(yīng)用的吞吐量, - 在垃圾收集過程中,會利用所有的核并行進行垃圾回收動作,降低應(yīng)用暫停時間 - 在垃圾回收間歇期,垃圾收集器不工作,不會消耗系統(tǒng)資源      另一方面,并行GC的所有階段都不能被中斷,所以這些垃圾收集器仍然有可能在所有應(yīng)用線程停止時陷入長時間的暫停中。所以,如果要求系統(tǒng)低延遲,那么不建議使用這種垃圾收集器。      接下來,我們看一下并行GC時的日志信息。如下所示,

2015-05-26T14:27:40.915-0200: 116.115: [GC (Allocation Failure) [PSYoungGen: 2694440K->1305132K(2796544K)] 9556775K->8438926K(11185152K), 0.2406675 secs] [Times: user=1.77sys=0.01, real=0.24 secs]2015-05-26T14:27:41.155-0200: 116.356: [Full GC (Ergonomics) [PSYoungGen: 1305132K->0K(2796544K)] [ParOldGen: 7133794K->6597672K(8388608K)] 8438926K->6597672K(11185152K),[Metaspace: 6745K->6745K(1056768K)], 0.9158801 secs] [Times: user=4.49 sys=0.64,real=0.92 secs]

1、Minor GC

  接下來詳細分析Minor GC時的日志信息。

2015-05-26T14:27:40.915-02001: 116.1152: [GC3 (Allocation Failure4) [PSYoungGen5: 2694440K->1305132K6(2796544K)7] 9556775K->8438926K8(11185152K)9, 0.2406675 secs10] [Times: user=1.77 sys=0.01, real=0.24 secs]11

   (1)2015-05-26T14:27:40.915-0200,本次GC事件發(fā)生的時間 (2)116.115,GC時JVM的啟動總時間,單位為秒。 (3)GC,用于區(qū)分Minor GC和Full GC。這里表示本次為Minor GC (4)Allocation Failure,導(dǎo)致本次GC的原因。是由于新生代中無法為新對象分配內(nèi)存 (5)PSYoungGen,垃圾收集器的名稱,這里表示這是一個并行標記復(fù)制,暫停全部應(yīng)用的新生代垃圾收集器 (6)2694440K->1305132K,GC前后新生代的內(nèi)存空間使用量 (7)2796544K,新生代總內(nèi)存量 (8)9556775K->8438926K,垃圾回收前后總堆內(nèi)存的變化情況(包括新生代和老年代) (9)11185152K,JVM堆的可用內(nèi)存 (10)0.2406675 secs,GC事件的耗時 (11)[Times: user=1.77 sys=0.01, real=0.24 secs],GC事件的耗時,

user- 表示在此次垃圾回收過程中,所有GC線程消耗的CPU時間之和sys - 表示GC過程中操作系統(tǒng)調(diào)用和系統(tǒng)等等事件所消耗的時間

real - 應(yīng)用暫停的總時間。在并行GC中,這個數(shù)值應(yīng)該接近于(user + sys) / GC線程數(shù)。即單個核上平均的暫停時間,在這里線程數(shù)為8。由于某些過程是不能并行執(zhí)行的,所以這個值會比剛才求的均值略高。

  總結(jié)一下本次GC過程就是,在GC前整個堆內(nèi)存使用了9556775K,其中新生代使用了2694440K,那么老年代使用了6862335K。新生代的GC導(dǎo)致新生代釋放了1389308K的空間,但是堆的總空間只釋放了1117849K。這意味著有271459K的對象從新生代升級到了老年代中,整個過程如下圖所示,      這里寫圖片描述

2、Full GC

  在理解了新生代的并行GC過程后,我們接下來分析一些并行GC在Full GC時的表現(xiàn),

2015-05-26T14:27:41.155-02001: 116.3562: [Full GC3 (Ergonomics4) [PSYoungGen: 1305132K->0K(2796544K)]5 [ParOldGen6: 7133794K->6597672K7(8388608K)8] 8438926K->6597672K9(11185152K)10,[Metaspace: 6745K->6745K(1056768K)]11, 0.9158801 secs12] [Times: user=4.49 sys=0.64,real=0.92 secs]13

   (1)2015-05-26T14:27:41.155-0200,本次GC事件發(fā)生的時間 (2)116.356,GC時JVM的啟動總時間,單位為秒。 (3)Full GC,表示本次是一次Full GC,將會對新生代和老年代的內(nèi)存空間進行回收 (4)Ergonomics,本次GC的觸發(fā)原因。這里是由于JVM認為此刻是一次適合進行垃圾回收的時間 (5)[PSYoungGen: 1305132K->0K(2796544K)],垃圾收集器的名稱。PSYoungGen表示這是一次新生代中進行的標記復(fù)制,暫停全部應(yīng)用的新生代GC。新生代的內(nèi)存空間使用量從1305132K降低到0。一般來說,進行了一次Full GC后,新生代的內(nèi)存空間將會被全部清理。 (6)ParOldGen,老年代中的垃圾收集器類型。在這里ParOldGen表示在老年代中使用的標記清除整理,暫停全部應(yīng)用的老年代垃圾收集器。 (7)133794K->6597672K,老年代垃圾回收前后的內(nèi)存使用情況 (8)8388608K,老年代的總內(nèi)存大小 (9)8438926K->6597672K,垃圾回收前后總堆內(nèi)存的變化情況(包括新生代和老年代) (10)11185152K,JVM堆的總內(nèi)存 (11)[Metaspace: 6745K->6745K(1056768K)],元數(shù)據(jù)區(qū)在垃圾回收前后的內(nèi)存使用情況,從這里可以看出,本次GC時并沒有對元數(shù)據(jù)區(qū)的內(nèi)存進行回收 (12)0.9158801 secs,本次GC的耗時,單位為秒 (13)[Times: user=4.49 sys=0.64,real=0.92 secs],GC事件的耗時,

user- 表示在此次垃圾回收過程中,所有GC線程消耗的CPU時間之和sys - 表示GC過程中操作系統(tǒng)調(diào)用和系統(tǒng)等等事件所消耗的時間real - 應(yīng)用暫停的總時間。在并行GC中,這個數(shù)值應(yīng)該接近于(user + sys) / GC線程數(shù)。即單個核上平均的暫停時間,在這里線程數(shù)為8。由于某些過程是不能并行執(zhí)行的,所以這個值會比剛才求的均值略高。      并行GC過程中的Full GC也與Minor GC有些不同。Full GC不僅會對新生代進行垃圾回收,也會清理老年代和元數(shù)據(jù)區(qū)。在Full GC前后,JVM各區(qū)內(nèi)存變化情況如下圖所示,      這里寫圖片描述

三、并發(fā)標記清除CMS(Concurrent Mark and Sweep)

四、G1(Garbage First)

五、 Shenandoah


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 额济纳旗| 秦皇岛市| 天等县| 新龙县| 麻栗坡县| 荥阳市| 瑞金市| 密山市| 嫩江县| 扬中市| 彰化县| 上饶县| 承德县| 泰和县| 惠东县| 炉霍县| 阳城县| 忻城县| 乐业县| 义马市| 临武县| 两当县| 华亭县| 乐山市| 周宁县| 盐山县| 田林县| 武清区| 鹤壁市| 阿坝| 孟津县| 通海县| 东宁县| 灌阳县| 张家口市| 昆山市| 津市市| 霞浦县| 三都| 汕尾市| 宝丰县|