真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

一文搞清楚MinorGC、MajorGC、FullGC之間的關(guān)系

前言

創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)、做網(wǎng)站,集網(wǎng)站策劃、網(wǎng)站設(shè)計、網(wǎng)站制作于一體,網(wǎng)站seo、網(wǎng)站優(yōu)化、網(wǎng)站營銷、軟文發(fā)稿等專業(yè)人才根據(jù)搜索規(guī)律編程設(shè)計,讓網(wǎng)站在運(yùn)行后,在搜索中有好的表現(xiàn),專業(yè)設(shè)計制作為您帶來效益的網(wǎng)站!讓網(wǎng)站建設(shè)為您創(chuàng)造效益。

文章要求讀者熟悉 JVM 內(nèi)置的通用垃圾回收原則。堆內(nèi)存劃分為 Eden、Survivor 和 Tenured/Old 空間,代假設(shè)和其他不同的 GC 算法超出了本文討論的范圍。

一文搞清楚Minor GC、Major GC 、Full GC 之間的關(guān)系

Minor GC

從年輕代空間(包括 Eden 和 Survivor 區(qū)域)回收內(nèi)存被稱為 Minor GC。這一定義既清晰又易于理解。但是,當(dāng)發(fā)生Minor GC事件的時候,有一些有趣的地方需要注意到:

1、當(dāng) JVM 無法為一個新的對象分配空間時會觸發(fā) Minor GC,比如當(dāng) Eden 區(qū)滿了。所以分配率越高,越頻繁執(zhí)行 Minor GC。

2、內(nèi)存池被填滿的時候,其中的內(nèi)容全部會被復(fù)制,指針會從0開始跟蹤空閑內(nèi)存。Eden 和 Survivor 區(qū)進(jìn)行了標(biāo)記和復(fù)制操作,取代了經(jīng)典的標(biāo)記、掃描、壓縮、清理操作。所以 Eden 和 Survivor 區(qū)不存在內(nèi)存碎片。寫指針總是停留在所使用內(nèi)存池的頂部。

3、執(zhí)行 Minor GC 操作時,不會影響到永久代。從永久代到年輕代的引用被當(dāng)成 GC roots,從年輕代到永久代的引用在標(biāo)記階段被直接忽略掉。

4、質(zhì)疑常規(guī)的認(rèn)知,所有的 Minor GC 都會觸發(fā)“全世界的暫停(stop-the-world)”,停止應(yīng)用程序的線程。對于大部分應(yīng)用程序,停頓導(dǎo)致的延遲都是可以忽略不計的。其中的真相就 是,大部分 Eden 區(qū)中的對象都能被認(rèn)為是垃圾,永遠(yuǎn)也不會被復(fù)制到 Survivor 區(qū)或者老年代空間。如果正好相反,Eden 區(qū)大部分新生對象不符合 GC 條件,Minor GC 執(zhí)行時暫停的時間將會長很多。

所以 Minor GC 的情況就相當(dāng)清楚了——每次 Minor GC 會清理年輕代的內(nèi)存。

一文搞清楚Minor GC、Major GC 、Full GC 之間的關(guān)系

Major GC vs Full GC

大家應(yīng)該注意到,目前,這些術(shù)語無論是在 JVM 規(guī)范還是在垃圾收集研究論文中都沒有正式的定義。但是我們一看就知道這些在我們已經(jīng)知道的基礎(chǔ)之上做出的定義是正確的,Minor GC 清理年輕帶內(nèi)存應(yīng)該被設(shè)計得簡單:

  • Major GC 是清理老年代。

  • Full GC 是清理整個堆空間—包括年輕代和老年代。

很不幸,實(shí)際上它還有點(diǎn)復(fù)雜且令人困惑。首先,許多 Major GC 是由 Minor GC 觸發(fā)的,所以很多情況下將這兩種 GC 分離是不太可能的。另一方面,許多現(xiàn)代垃圾收集機(jī)制會清理部分永久代空間,所以使用“cleaning”一詞只是部分正確。

這使得我們不用去關(guān)心到底是叫 Major GC 還是 Full GC,大家應(yīng)該關(guān)注當(dāng)前的 GC 是否停止了所有應(yīng)用程序的線程,還是能夠并發(fā)的處理而不用停掉應(yīng)用程序的線程。

這種混亂甚至內(nèi)置到 JVM 標(biāo)準(zhǔn)工具。下面一個例子很好的解釋了我的意思。讓我們比較兩個不同的工具 Concurrent Mark 和 Sweep collector (-XX:+UseConcMarkSweepGC)在 JVM 中運(yùn)行時輸出的跟蹤記錄。

第一次嘗試通過 jstat 輸出:

my-precious:?me$?jstat?-gc?-t?4235?1sTime?S0C????S1C????S0U????S1U??????EC???????EU????????OC?????????OU???????MC?????MU????CCSC???CCSU???YGC?????YGCT????FGC????FGCT?????GCT????5.7?34048.0?34048.0??0.0???34048.0?272640.0?194699.7?1756416.0???181419.9??18304.0?17865.1?2688.0?2497.6??????3????0.275???0??????0.000????0.275?6.7?34048.0?34048.0?34048.0??0.0???272640.0?247555.4?1756416.0???263447.9??18816.0?18123.3?2688.0?2523.1??????4????0.359???0??????0.000????0.359?7.7?34048.0?34048.0??0.0???34048.0?272640.0?257729.3?1756416.0???345109.8??19072.0?18396.6?2688.0?2550.3??????5????0.451???0??????0.000????0.451?8.7?34048.0?34048.0?34048.0?34048.0?272640.0?272640.0?1756416.0??444982.5??19456.0?18681.3?2816.0?2575.8??????7????0.550???0??????0.000????0.550?9.7?34048.0?34048.0?34046.7??0.0???272640.0?16777.0??1756416.0???587906.3??20096.0?19235.1?2944.0?2631.8??????8????0.720???0??????0.000????0.72010.7?34048.0?34048.0??0.0???34046.2?272640.0?80171.6??1756416.0???664913.4??20352.0?19495.9?2944.0?2657.4??????9????0.810???0??????0.000????0.81011.7?34048.0?34048.0?34048.0??0.0???272640.0?129480.8?1756416.0???745100.2??20608.0?19704.5?2944.0?2678.4?????10????0.896???0??????0.000????0.89612.7?34048.0?34048.0??0.0???34046.6?272640.0?164070.7?1756416.0???822073.7??20992.0?19937.1?3072.0?2702.8?????11????0.978???0??????0.000????0.97813.7?34048.0?34048.0?34048.0??0.0???272640.0?211949.9?1756416.0???897364.4??21248.0?20179.6?3072.0?2728.1?????12????1.087???1??????0.004????1.09114.7?34048.0?34048.0??0.0???34047.1?272640.0?245801.5?1756416.0???597362.6??21504.0?20390.6?3072.0?2750.3?????13????1.183???2??????0.050????1.23315.7?34048.0?34048.0??0.0???34048.0?272640.0?21474.1??1756416.0???757347.0??22012.0?20792.0?3200.0?2791.0?????15????1.336???2??????0.050????1.38616.7?34048.0?34048.0?34047.0??0.0???272640.0?48378.0??1756416.0???838594.4??22268.0?21003.5?3200.0?2813.2?????16????1.433???2??????0.050????1.484

這個片段是 JVM 啟動后第17秒提取的。基于該信息,我們可以得出這樣的結(jié)果,運(yùn)行了12次 Minor GC、2次 Full GC,時間總跨度為50毫秒。通過 jconsole 或者 jvisualvm 這樣的基于GUI的工具你能得到同樣的結(jié)果。

java?-XX:+PrintGCDetails?-XX:+UseConcMarkSweepGC?eu.plumbr.demo.GarbageProducer3.157:?[GC?(Allocation?Failure)?3.157:?[ParNew:?272640K->34048K(306688K),?0.0844702?secs]?272640K->69574K(2063104K),?0.0845560?secs]?[Times:?user=0.23?sys=0.03,?real=0.09?secs]?4.092:?[GC?(Allocation?Failure)?4.092:?[ParNew:?306688K->34048K(306688K),?0.1013723?secs]?342214K->136584K(2063104K),?0.1014307?secs]?[Times:?user=0.25?sys=0.05,?real=0.10?secs]?...?cut?for?brevity?...11.292:?[GC?(Allocation?Failure)?11.292:?[ParNew:?306686K->34048K(306688K),?0.0857219?secs]?971599K->779148K(2063104K),?0.0857875?secs]?[Times:?user=0.26?sys=0.04,?real=0.09?secs]?12.140:?[GC?(Allocation?Failure)?12.140:?[ParNew:?306688K->34046K(306688K),?0.0821774?secs]?1051788K->856120K(2063104K),?0.0822400?secs]?[Times:?user=0.25?sys=0.03,?real=0.08?secs]?12.989:?[GC?(Allocation?Failure)?12.989:?[ParNew:?306686K->34048K(306688K),?0.1086667?secs]?1128760K->931412K(2063104K),?0.1087416?secs]?[Times:?user=0.24?sys=0.04,?real=0.11?secs]?13.098:?[GC?(CMS?Initial?Mark)?[1?CMS-initial-mark:?897364K(1756416K)]?936667K(2063104K),?0.0041705?secs]?[Times:?user=0.02?sys=0.00,?real=0.00?secs]?13.102:?[CMS-concurrent-mark-start]13.341:?[CMS-concurrent-mark:?0.238/0.238?secs]?[Times:?user=0.36?sys=0.01,?real=0.24?secs]?13.341:?[CMS-concurrent-preclean-start]13.350:?[CMS-concurrent-preclean:?0.009/0.009?secs]?[Times:?user=0.03?sys=0.00,?real=0.01?secs]?13.350:?[CMS-concurrent-abortable-preclean-start]13.878:?[GC?(Allocation?Failure)?13.878:?[ParNew:?306688K->34047K(306688K),?0.0960456?secs]?1204052K->1010638K(2063104K),?0.0961542?secs]?[Times:?user=0.29?sys=0.04,?real=0.09?secs]?14.366:?[CMS-concurrent-abortable-preclean:?0.917/1.016?secs]?[Times:?user=2.22?sys=0.07,?real=1.01?secs]?14.366:?[GC?(CMS?Final?Remark)?[YG?occupancy:?182593?K?(306688?K)]14.366:?[Rescan?(parallel)?,?0.0291598?secs]14.395:?[weak?refs?processing,?0.0000232?secs]14.395:?[class?unloading,?0.0117661?secs]14.407:?[scrub?symbol?table,?0.0015323?secs]14.409:?[scrub?string?table,?0.0003221?secs][1?CMS-remark:?976591K(1756416K)]?1159184K(2063104K),?0.0462010?secs]?[Times:?user=0.14?sys=0.00,?real=0.05?secs]?14.412:?[CMS-concurrent-sweep-start]14.633:?[CMS-concurrent-sweep:?0.221/0.221?secs]?[Times:?user=0.37?sys=0.00,?real=0.22?secs]?14.633:?[CMS-concurrent-reset-start]14.636:?[CMS-concurrent-reset:?0.002/0.002?secs]?[Times:?user=0.00?sys=0.00,?real=0.00?secs]

在點(diǎn)頭同意這個結(jié)論之前,讓我們看看來自同一個 JVM 啟動收集的垃圾收集日志的輸出。顯然- XX :+ PrintGCDetails 告訴我們一個不同且更詳細(xì)的故事:

基于這些信息,我們可以看到12次 Minor GC 后開始有些和上面不一樣了。沒有運(yùn)行兩次 Full GC,這不同的地方在于單個 GC 在永久代中不同階段運(yùn)行了兩次:

1、最初的標(biāo)記階段,用了0.0041705秒也就是4ms左右。這個階段會暫?!叭澜纾?stop-the-world)”的事件,停止所有應(yīng)用程序的線程,然后開始標(biāo)記。

2、并行執(zhí)行標(biāo)記和清洗階段。這些都是和應(yīng)用程序線程并行的。

3、最后 Remark 階段,花費(fèi)了0.0462010秒約46ms。這個階段會再次暫停所有的事件。

4、并行執(zhí)行清理操作。正如其名,此階段也是并行的,不會停止其他線程。

所以,正如我們從垃圾回收日志中所看到的那樣,實(shí)際上只是執(zhí)行了 Major GC 去清理老年代空間而已,而不是執(zhí)行了兩次 Full GC。

如果你是后期做決 定的話,那么由 jstat 提供的數(shù)據(jù)會引導(dǎo)你做出正確的決策。它正確列出的兩個暫停所有事件的情況,導(dǎo)致所有線程停止了共計50ms。但是如果你試圖優(yōu)化吞吐量,你會被誤導(dǎo)的。清 單只列出了回收初始標(biāo)記和最終 Remark 階段,jstat的輸出看不到那些并發(fā)完成的工作。

一文搞清楚Minor GC、Major GC 、Full GC 之間的關(guān)系

結(jié)論

考慮到這種情況,最好避免以 Minor、Major、Full GC 這種方式來思考問題。而應(yīng)該監(jiān)控應(yīng)用延遲或者吞吐量,然后將 GC 事件和結(jié)果聯(lián)系起來。

歡迎大家關(guān)注我的公種浩【程序員追風(fēng)】,文章都會在里面更新,整理的資料也會放在里面。

隨著這些 GC 事件的發(fā)生,你需要額外的關(guān)注某些信息,GC 事件是強(qiáng)制所有應(yīng)用程序線程停止了還是并行的處理了部分事件。

最后

歡迎大家一起交流,喜歡文章記得關(guān)注我點(diǎn)個贊喲,感謝支持!


網(wǎng)頁標(biāo)題:一文搞清楚MinorGC、MajorGC、FullGC之間的關(guān)系
當(dāng)前網(wǎng)址:http://weahome.cn/article/psdsch.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部