大家好,我是【運(yùn)維開(kāi)發(fā)故事公眾號(hào)】的 Java 程序員老鄭。JVM 是我們從事 Java 項(xiàng)目和開(kāi)發(fā)都需要具備的非常底層的基礎(chǔ)知識(shí)。
首先我先拋出以下幾個(gè)問(wèn)題:
作為 5 年以上工作經(jīng)驗(yàn)的技術(shù)人員,或多或少在系統(tǒng)維護(hù),系統(tǒng)保障,系統(tǒng)調(diào)優(yōu)遇到過(guò)上面的這幾個(gè)場(chǎng)景,你可能是通過(guò)重啟,調(diào)整一些 jvm 參數(shù)解決,如果大家需要深入的探究找到問(wèn)題的原因,可以耐心看看下文我對(duì) G1 的一些總結(jié)。
G1 的英文全稱是 Garbagge First,是一個(gè)有分代,按照 Region 的方式進(jìn)行內(nèi)存布局的垃圾收集器。
上圖,我將一些 Region 標(biāo)明了 H,它代表Humongous,這表示這些 Region 存儲(chǔ)的是巨大對(duì)象(humongous object,H-obj),即大小大于等于 region 一半的對(duì)象。H-obj 有如下幾個(gè)特征:
Collection Set 就是我們垃圾收集器的一個(gè)區(qū)域,在不同的垃圾回收階段,會(huì)有不同的區(qū)域。
Young GC 主要是清理,新生代中的對(duì)象,我們知道整個(gè)堆空間包括老年代,新生代,我們?cè)?Young GC 過(guò)程中會(huì)去找 GCRoots 然后判斷對(duì)象是是否可達(dá), 如果不可達(dá),如果可達(dá)就標(biāo)記。如果對(duì)于老年代中引用新生代的對(duì)象,我們?nèi)绻页鰜?lái)就就需要對(duì)老年代進(jìn)行全掃描,這樣是不太現(xiàn)實(shí)的。所以 G1 通過(guò)記憶集的形式記錄了老年代對(duì)新生代的引用。具體在 G1 中通過(guò) CarTable 來(lái)實(shí)現(xiàn)記憶集。
記錄了其它 Region 中的對(duì)象到 Region 的引用。RSet 的價(jià)值在于使得垃圾回收不需要掃描整個(gè)堆,能夠快速定位到真正引用它的堆對(duì)象地址。ReSet 本身就是一個(gè) Hash 表,存儲(chǔ)在新生代的每個(gè) Region 中。但是存儲(chǔ)需要消耗空間,多的能達(dá)到百分之 20。因此G1對(duì)內(nèi)存的空間要求較高(小空間沒(méi)資本玩),空間越大性能越彪悍。
由于新生代GC時(shí),需要掃描整個(gè)old區(qū),效率非常低。所以old區(qū)就是用卡表的方式進(jìn)行一次邏輯分區(qū)。一般一頁(yè)卡表的大小是2的n次冪。每一個(gè)區(qū)域也是用Key,Value結(jié)構(gòu)進(jìn)行記錄。每一區(qū)域記錄為Key不重復(fù),Value則記錄這片區(qū)域的老年代對(duì)象與新生代對(duì)象是否存在引用關(guān)系,存在則標(biāo)記為1,否則為0。記錄完畢后把value為1的key作為ReSet的key進(jìn)行記錄,并且ReSet的value存儲(chǔ)引用,從而提高跨代引用的查詢效率。
所有的預(yù)測(cè)都是基于歷史的擬合,HotSpot使用了基于方差與標(biāo)準(zhǔn)差的技術(shù)。參考:https://sdww2348115.github.io/jvm/g1/PausePredictionModel。
圖片來(lái)源 Oracle 官網(wǎng)
G1 有兩個(gè)階段,它會(huì)在這兩個(gè)階段往返,分別是 Young-only,Space Reclamation.
圖是來(lái)自 Oracle 上對(duì) GC 周期的描述,實(shí)心圓都表示一次 GC 停頓
在幾次 GC 后,Old gen 的對(duì)象占有比超過(guò)了 InitiatingHeapOccupancyPercent (簡(jiǎn)稱為IHOP,默認(rèn)值為45,這個(gè)值是啟動(dòng)并發(fā)標(biāo)記的閾值,當(dāng)老年代使用內(nèi)存占用堆內(nèi)存的45%啟動(dòng)并發(fā)標(biāo)記。如果該區(qū)域過(guò)大,可能會(huì)導(dǎo)致mixed gc跟不上內(nèi)存分配的速度從而導(dǎo)致full gc ),gc 就會(huì)進(jìn)入并發(fā)標(biāo)記準(zhǔn)備 (Concurrent Mark)。
Mixed GC 依賴 Concurrent Mark。
回到 Full GC,從上面簡(jiǎn)單分析得出,F(xiàn)ull GC 發(fā)生是沒(méi)有足夠的 free region,如果堆是足夠大的,Mixed gc 沒(méi)有回收足夠的 old region,或者 concurrent mark 沒(méi)法及時(shí)完成,都可能會(huì)導(dǎo)致 full gc。
下面是網(wǎng)上找的一個(gè) GC 日志案例,解析如下(配合 G1 垃圾收集周期結(jié)合來(lái)看):
[gc,start ] GC(44265) Pause Young (Normal) (G1 Evacuation Pause)[gc,task ] GC(44265) Using 13 workers of 13 for evacuation[gc,phases ] GC(44265) Pre Evacuate Collection Set: 0.1ms[gc,phases ] GC(44265) Evacuate Collection Set: 101.8ms[gc,phases ] GC(44265) Post Evacuate Collection Set: 3.2ms[gc,phases ] GC(44265) Other: 2.7ms[gc,heap ] GC(44265) Eden regions: 1850->0(1851)[gc,heap ] GC(44265) Survivor regions: 70->69(240)[gc,heap ] GC(44265) Old regions: 766->768[gc,heap ] GC(44265) Humongous regions: 20->19[gc,metaspace ] GC(44265) Metaspace: 193280K->193280K(1230848K)[gc ] GC(44265) Pause Young (Normal) (G1 Evacuation Pause) 21642M->6843M(25600M) 107.561ms[gc,cpu ] GC(44265) User=1.31s Sys=0.00s Real=0.11s[gc,start ] GC(44266) Pause Young (Normal) (G1 Evacuation Pause)[gc,task ] GC(44266) Using 13 workers of 13 for evacuation[gc,phases ] GC(44266) Pre Evacuate Collection Set: 0.1ms[gc,phases ] GC(44266) Evacuate Collection Set: 99.8ms[gc,phases ] GC(44266) Post Evacuate Collection Set: 3.3ms[gc,phases ] GC(44266) Other: 2.7ms[gc,heap ] GC(44266) Eden regions: 1851->0(1854)[gc,heap ] GC(44266) Survivor regions: 69->66(240)[gc,heap ] GC(44266) Old regions: 768->772[gc,heap ] GC(44266) Humongous regions: 20->19[gc,metaspace ] GC(44266) Metaspace: 193280K->193280K(1230848K)[gc ] GC(44266) Pause Young (Normal) (G1 Evacuation Pause) 21659M->6848M(25600M) 105.713ms[gc,cpu ] GC(44266) User=1.29s Sys=0.01s Real=0.10s[gc,start ] GC(44267) Pause Young (Normal) (G1 Evacuation Pause)[gc,task ] GC(44267) Using 13 workers of 13 for evacuation[gc,phases ] GC(44267) Pre Evacuate Collection Set: 0.1ms //初始標(biāo)記,查找 gc root [gc,phases ] GC(44267) Evacuate Collection Set: 89.8ms //并發(fā)標(biāo)記[gc,phases ] GC(44267) Post Evacuate Collection Set: 3.5ms //清理工作[gc,phases ] GC(44267) Other: 2.7ms[gc,heap ] GC(44267) Eden regions: 1854->0(1856)[gc,heap ] GC(44267) Survivor regions: 66->64(240)[gc,heap ] GC(44267) Old regions: 772->775[gc,heap ] GC(44267) Humongous regions: 20->19[gc,metaspace ] GC(44267) Metaspace: 193280K->193280K(1230848K)[gc ] GC(44267) Pause Young (Normal) (G1 Evacuation Pause) 21688M->6859M(25600M) 95.891ms[gc,cpu ] GC(44267) User=1.16s Sys=0.00s Real=0.10s[gc,start ] GC(44268) Pause Young (Normal) (G1 Evacuation Pause) // Young GC[gc,task ] GC(44268) Using 13 workers of 13 for evacuation[gc,phases ] GC(44268) Pre Evacuate Collection Set: 0.1ms[gc,phases ] GC(44268) Evacuate Collection Set: 100.5ms[gc,phases ] GC(44268) Post Evacuate Collection Set: 3.8ms[gc,phases ] GC(44268) Other: 2.8ms[gc,heap ] GC(44268) Eden regions: 1856->0(1855)[gc,heap ] GC(44268) Survivor regions: 64->65(240)[gc,heap ] GC(44268) Old regions: 775->777[gc,heap ] GC(44268) Humongous regions: 20->19[gc,metaspace ] GC(44268) Metaspace: 193280K->193280K(1230848K)[gc ] GC(44268) Pause Young (Normal) (G1 Evacuation Pause) 21715M->6876M(25600M) 107.037ms[gc,cpu ] GC(44268) User=1.30s Sys=0.00s Real=0.11s[gc,start ] GC(44269) Pause Young (Concurrent Start) (G1 Humongous Allocation) // 并發(fā)階段[gc,task ] GC(44269) Using 13 workers of 13 for evacuation[gc,phases ] GC(44269) Pre Evacuate Collection Set: 0.6ms[gc,phases ] GC(44269) Evacuate Collection Set: 90.9ms[gc,phases ] GC(44269) Post Evacuate Collection Set: 3.2ms[gc,phases ] GC(44269) Other: 2.9ms[gc,heap ] GC(44269) Eden regions: 1519->0(1855)[gc,heap ] GC(44269) Survivor regions: 65->65(240)[gc,heap ] GC(44269) Old regions: 777->777[gc,heap ] GC(44269) Humongous regions: 19->19[gc,metaspace ] GC(44269) Metaspace: 193280K->193280K(1230848K)[gc ] GC(44269) Pause Young (Concurrent Start) (G1 Humongous Allocation) 19024M->6883M(25600M) 97.391ms[gc,cpu ] GC(44269) User=1.16s Sys=0.01s Real=0.10s[gc ] GC(44270) Concurrent Cycle // 完成 clearup[gc,marking ] GC(44270) Concurrent Clear Claimed Marks[gc,marking ] GC(44270) Concurrent Clear Claimed Marks 0.562ms[gc,marking ] GC(44270) Concurrent Scan Root Regions[gc,marking ] GC(44270) Concurrent Scan Root Regions 719.931ms[gc,marking ] GC(44270) Concurrent Mark (280799.914s)[gc,marking ] GC(44270) Concurrent Mark From Roots[gc,task ] GC(44270) Using 3 workers of 3 for marking[gc,marking ] GC(44270) Concurrent Mark From Roots 2268.905ms[gc,marking ] GC(44270) Concurrent Preclean[gc,marking ] GC(44270) Concurrent Preclean 3.078ms[gc,marking ] GC(44270) Concurrent Mark (280799.914s, 280802.186s) 2272.068ms[gc,start ] GC(44270) Pause Remark[gc,stringtable] GC(44270) Cleaned string and symbol table, strings: 87967 processed, 92 removed, symbols: 442773 processed, 13 removed[gc ] GC(44270) Pause Remark 13740M->13740M(25600M) 32.599ms[gc,cpu ] GC(44270) User=0.29s Sys=0.00s Real=0.04s[gc,marking ] GC(44270) Concurrent Rebuild Remembered Sets //重構(gòu)記憶集[gc,marking ] GC(44270) Concurrent Rebuild Remembered Sets 1906.792ms[gc,start ] GC(44270) Pause Cleanup[gc ] GC(44270) Pause Cleanup 18019M->18019M(25600M) 0.782ms[gc,cpu ] GC(44270) User=0.00s Sys=0.01s Real=0.00s[gc,marking ] GC(44270) Concurrent Cleanup for Next Mark[gc,marking ] GC(44270) Concurrent Cleanup for Next Mark 25.530ms[gc ] GC(44270) Concurrent Cycle 4963.833ms[gc,start ] GC(44271) Pause Young (Prepare Mixed) (G1 Evacuation Pause) // Space Reclamation 階段了,多個(gè) Mixed GC 會(huì)進(jìn)行[gc,task ] GC(44271) Using 13 workers of 13 for evacuation[gc,phases ] GC(44271) Pre Evacuate Collection Set: 0.1ms[gc,phases ] GC(44271) Evacuate Collection Set: 102.6ms[gc,phases ] GC(44271) Post Evacuate Collection Set: 3.7ms[gc,phases ] GC(44271) Other: 3.9ms[gc,heap ] GC(44271) Eden regions: 1855->0(98)[gc,heap ] GC(44271) Survivor regions: 65->62(240)[gc,heap ] GC(44271) Old regions: 777->778[gc,heap ] GC(44271) Humongous regions: 21->19[gc,metaspace ] GC(44271) Metaspace: 193271K->193271K(1230848K)[gc ] GC(44271) Pause Young (Prepare Mixed) (G1 Evacuation Pause) 21739M->6869M(25600M) 110.034ms[gc,cpu ] GC(44271) User=1.32s Sys=0.01s Real=0.10s[gc,start ] GC(44272) Pause Young (Mixed) (G1 Evacuation Pause)[gc,task ] GC(44272) Using 13 workers of 13 for evacuation[gc,phases ] GC(44272) Pre Evacuate Collection Set: 0.4ms[gc,phases ] GC(44272) Evacuate Collection Set: 150.8ms[gc,phases ] GC(44272) Post Evacuate Collection Set: 3.2ms[gc,phases ] GC(44272) Other: 2.3ms[gc,heap ] GC(44272) Eden regions: 98->0(149)[gc,heap ] GC(44272) Survivor regions: 62->11(20)[gc,heap ] GC(44272) Old regions: 778->547[gc,heap ] GC(44272) Humongous regions: 19->19[gc,metaspace ] GC(44272) Metaspace: 193271K->193271K(1230848K)[gc ] GC(44272) Pause Young (Mixed) (G1 Evacuation Pause) 7653M->4605M(25600M) 156.486ms[gc,cpu ] GC(44272) User=1.95s Sys=0.01s Real=0.15s[gc,start ] GC(44273) Pause Young (Mixed) (G1 Evacuation Pause)[gc,task ] GC(44273) Using 13 workers of 13 for evacuation[gc,phases ] GC(44273) Pre Evacuate Collection Set: 0.2ms[gc,phases ] GC(44273) Evacuate Collection Set: 122.9ms[gc,phases ] GC(44273) Post Evacuate Collection Set: 2.0ms[gc,phases ] GC(44273) Other: 3.1ms[gc,heap ] GC(44273) Eden regions: 149->0(1900)[gc,heap ] GC(44273) Survivor regions: 11->20(20)[gc,heap ] GC(44273) Old regions: 547->520[gc,heap ] GC(44273) Humongous regions: 19->19[gc,metaspace ] GC(44273) Metaspace: 193271K->193271K(1230848K)[gc ] GC(44273) Pause Young (Mixed) (G1 Evacuation Pause) 5797M->4468M(25600M) 128.036ms[gc,cpu ] GC(44273) User=1.57s Sys=0.01s Real=0.12s
上面是連續(xù)幾次 GC 的日志,可以對(duì)照著 GC 周期來(lái)看。
這里簡(jiǎn)單說(shuō)一下 humongous 對(duì)象的處理,humongous 對(duì)象在 G1 中是被特殊對(duì)待的,G1 只決定它們是否生存,回收他們占用的空間,從不會(huì)移動(dòng)它們。
- Young-Only 階段,humongous regions 可能會(huì)被回收。
- Space-Reclamation,humongous regions 可能會(huì)被回收。
我們可以通過(guò)以下幾種工具輔助分析 JVM 性能瓶頸:
綜合組件:
thread dump 分析:
gc 日志分析:
heap dump 分析:
【GC 停頓預(yù)測(cè)模型】
【垃圾收集器執(zhí)行過(guò)程】
【跨代引用】
【空閑時(shí)自動(dòng)將Java堆內(nèi)存返回給操作系統(tǒng)】。
【其他】
本文鏈接:http://www.www897cc.com/showinfo-26-26558-0.htmlJava11 的 G1 垃圾收集器
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com
上一篇: 高效設(shè)計(jì)企業(yè)營(yíng)銷(xiāo)系統(tǒng)的三種方案復(fù)盤(pán)