G1 GC知識點:
Region:1M~64M,2的冪,默認為其大小為將堆分為約2048個region為宜奄抽。可以通過-XX:G1HeapRegionSize來設(shè)定region大小甩鳄,但是不推薦這么做如孝,region過少會導(dǎo)致G1的靈活性降低,掃描的時間增長娩贷。
free list:由空的region組成的linked list
GC 過程如下:
1.當(dāng)一個對象需要分配時第晰,首先從free list里獲取一個region的TLAB(Thread Local Allocation Buffer)本地線程緩沖區(qū),然后在這個TLAB上進行分配彬祖。
2. 以此類推茁瘦,直到所有Eden的region的總量都被填滿,就會觸發(fā)一次young GC储笑。這里的cumulative amount of Eden space 跟目標(biāo)暫停時間有關(guān)甜熔,在堆的5%~60%之間波動,其大小跟上次young GC的表現(xiàn)有關(guān)突倍。
3. 當(dāng)上述young GC完成后腔稀,死亡的對象被回收,存活的對象經(jīng)過疏散和壓縮后拷貝到Survivor區(qū)羽历,而年齡超過閾值(可以通過MaxTenuringThreshold設(shè)置焊虏,默認15)的則會晉升到old區(qū)。
4. 如果滿足如下三種情況之一秕磷,G1收集會繼續(xù)
? ? a. occupancy higher than threshold?達到the InitiatingHeapOccupancyPercent (IHOP)诵闭,old regions里分配的對象大于堆的45%(G1HeapWastePercent參數(shù))
? ? b. candidate old regions available 達到G1ReservePercent (G1MixedGCLiveThresholdPercent defaults to 85% in JDK8u40+ and 65% in JDK7)
? ? c. 遇到巨型數(shù)據(jù)的分配
5. 并發(fā)標(biāo)記。基于snapshot-at-the-beginning (SATB)標(biāo)記算法疏尿,在GC開始時先創(chuàng)建一個對象快照瘟芝,STAB可以在并發(fā)標(biāo)記時標(biāo)記所有快照中當(dāng)時的存活對象。標(biāo)記過程中新分配的對象也會被標(biāo)記為存活對象褥琐,不會被回收锌俱。
6. 當(dāng)并發(fā)標(biāo)記完成后,會再觸發(fā)一個young GC敌呈,然后再出發(fā)一個mixed GC贸宏。mixed GC與young GC主要有2點不同,mixed GC會回收包括Eden和old區(qū)的對象驱富,二者觸發(fā)的條件不一樣。
初級標(biāo)記(Mandatory):
根據(jù)參數(shù)‘-XX:+PrintGCDetails’匹舞,產(chǎn)生如下log
1. 信息總覽:
????a. 通過設(shè)置?‘-XX:+PrintGCDateStamps’ 得到GC發(fā)生的準備日期時間 -?2016-12-12T10:40:18.811-0500
? ? b. JVM啟動到當(dāng)前時間的相對時間?-?29.959
? ? c. 收集的類型?-?G1 Evacuation Pause (young)
? ? d. 垃圾收集消耗的總時長?-?0.0305171 sec?
2. 并行任務(wù):
? ? a.?Parallel Time - 并行任務(wù)STW總時長?- 26.6ms
? ? b. GC Workers?- 并行GC workers的總數(shù)量褐鸥,通過?"-XX:ParallelGCThreads"設(shè)置 - 4
? ? ? ? i. 當(dāng)cpu內(nèi)核數(shù) <= 8,設(shè)置為cpu核數(shù)赐稽;>8時叫榕,設(shè)置為核數(shù)的5/8
? ? c.?GC Worker Start?- GCworker開始工作時間相對于JVM啟動的最大最小時間,diff就是第一個線程啟動與最后一個線程啟動時間之差姊舵,這個差值肯定越小越好
? ? d.?Ext?Root Scanning - 外部根區(qū)(堆外區(qū)晰绎,線程棧根,JNI括丁,全局變量荞下,系統(tǒng)目錄,classloader等)掃描消耗時間
? ? e.?Update RS (Remembered Set or RSet) - 在每次開始收集之前都要進行Rset更新史飞,保證RSet是最新的尖昏。-XX:MaxGCPauseMillis參數(shù)是限制G1的暫停時間,一般RSet更新的時間小于10%的目標(biāo)暫停時間是比較可取的构资。如果花費在RSetUpdate的時間過長抽诉,可以修改其占用總暫停時間的百分比-XX:G1RSetUpdatingPauseTimePercent。這個參數(shù)的默認值是10吐绵。
? ? f.? Scan RS?- 掃描每個Region的RSet迹淌,尋找被待收集集合引用的區(qū)域? ??
? ? g. Code Root Scanning?- 掃描被待收集集合引用的編譯源碼根節(jié)點
? ? h.?Object Copy - 將待收集集合中所有存活的對象拷貝到新的區(qū)域
? ? i.? Termination?- 當(dāng)一個GC worker結(jié)束工作后,需要等待其他線程己单,并嘗試幫其他線程完成為完成的task. 結(jié)束時間指的就是這個線程結(jié)束收集到真正結(jié)束的時間差
? ? j. GC Worker Other?-?花在GC之外的工作線程的時間唉窃,比如因為JVM的某個活動,導(dǎo)致GC線程被停掉纹笼。這部分消耗的時間不是真正花在GC上句携,只是作為log的一部分記錄
? ? k.?GC Worker Total - 每個并行回收線程的時間統(tǒng)計
? ? l. GC Worker End?- GC相對于JVM啟動的結(jié)束時間. diff指第一個和最后一個完成的線程之間差值,越小越好
3. 串行任務(wù):
? ? a.?Code Root Fixup - 遍歷那些指向CSet的方法允乐,修正指針
? ? b.?Code Root Purge - 清理code root table
? ? c.?Clear CT?- 清除card table里的臟cards
4. 其他串行操作:
? ? a.?Choose CSet - 選取CSet
? ? b.?Ref Proc - 處理STW引用處理器發(fā)現(xiàn)的soft/weak/final/phantom/JNI引用
? ? c. Ref?Enq?- 將引用排列到相應(yīng)的reference隊列里
? ? d. Reditry?Cards?- 在回收過程中被修改的cards標(biāo)記為臟卡
? ? e. Humongous Register?- 在youngGC的時候會收集巨型區(qū)域矮嫉。這個指標(biāo)是指評估巨型區(qū)域是否足夠記錄的時間削咆。
? ? f.?Humongous Reclaim - 確認巨型對象死亡并清理,釋放巨型對象區(qū)域蠢笋,重置區(qū)域類型拨齐,將該區(qū)域放回空閑隊列所用的時間
? ? g. Free CSet?-?釋放CSet,其中也會清理CSet中的RSet,將其放回空閑隊列
5. 各個代的變化統(tǒng)計
? ? a.?Eden: 1097.0M(1097.0M)->0.0B(967.0M)
? ? ? ? i. 該次Young GC被觸發(fā)是因為Eden區(qū)滿了
? ? ? ? ii. Eden區(qū)通過該次垃圾回收被清空昨寞,變?yōu)?.0B
? ? ? ? iii. Eden區(qū)的總?cè)萘孔兓?097M -> 967M
? ? b.?Survivors: 13.0M->139.0M
? ? ? ? i. Survivor space從13M增長到139M
? ? c.?Heap: 1694.4M(2048.0M)->736.3M(2048.0M)
? ? ? ? i. 收集的時候瞻惋,整個堆總量為2048M,被使用了1694M
? ? ? ? ii. 回收完畢援岩,整個堆總量為2048M歼狼,被使用了736.3M
6. 垃圾回收花費的時間
? ? a.?user=0.08 - 在回收過程中花費在用戶代碼上的CPU時間,是所有thread在所有CPU上的花費時間之和享怀。并沒有計算處理器之外花費的時間和等待時間
? ? b.?sys=0.00 -?在回收過程中花費在內(nèi)核處理上的CPU時間羽峰,是所有thread在所有CPU上的花費時間之和。并沒有計算處理器之外花費的時間和等待時間
? ? c.?real=0.03 - 從垃圾回收到結(jié)束的真實時間添瓷,包括其他處理器花費的時候及等待時間
并發(fā)標(biāo)記的分析梅屉,并發(fā)標(biāo)記可以由不同的方式觸發(fā),但是它的表現(xiàn)是一致的鳞贷。
1. 標(biāo)記開始:
? ? GC pause (G1 Evacuation Pause) (young) (initial-mark)
? ? 標(biāo)記GC Roots坯汤,會STW,尋找所有可達到的對象搀愧,初始標(biāo)記階段是Young GC的一部分惰聂。初始標(biāo)記階段設(shè)置2種TAMS變量來區(qū)分現(xiàn)存的對象和并行標(biāo)記時才分配的對象。上述被標(biāo)記的對象被認為是存貨的對象咱筛。
2. 第一次并發(fā)事件:
? ? GC concurrent-root-region-scan-start /?GC concurrent-root-region-scan-end
? ? 根分區(qū)掃描庶近,這個階段GC的線程可以和應(yīng)用線程并發(fā)運行。其主要掃描初始標(biāo)記以及之前YoungGC對象轉(zhuǎn)移到的Survivor分區(qū)眷蚓,并標(biāo)記Survivor區(qū)中引用的對象鼻种。
3. 并發(fā)標(biāo)記
????GC concurrent-mark-start /?GC concurrent-mark-end
? ? a. 跟應(yīng)用線程同時運行,并發(fā)標(biāo)記的線程數(shù)默認為parallel thread的25%沙热,也可以通過”-XX:ConcGCThreads” 設(shè)置
? ? b.?會并發(fā)標(biāo)記所有非完全空閑的分區(qū)的存活對象叉钥,也即使用了SATB算法,標(biāo)記各個分區(qū)
4. 最終標(biāo)記
? ??GC remark [ Finalize Marking / GC ref-proc / Unloading]
? ? 有STW篙贸,主要處理SATB緩沖區(qū)投队,以及并發(fā)標(biāo)記階段未標(biāo)記到的漏網(wǎng)之魚(存活對象)
5.?清除階段
? ? ?GC cleanup 有STW
? ? a. 每個區(qū)域分別統(tǒng)計存活對象。在card bitmap標(biāo)記初始標(biāo)記之后分配的對象爵川,在Region bitmap標(biāo)記有存貨對象的區(qū)域
? ? b. 交換bitmaps敷鸦,為下一次標(biāo)記做準備
? ? c. 釋放和清理死去的老年區(qū)域和沒有存貨數(shù)據(jù)的巨型數(shù)據(jù)區(qū)域
? ? d. 清除沒有存活對象的區(qū)域的RSet
? ? e. 將老年區(qū)域根據(jù)存活率進行排序
? ? f.? 并發(fā)的將無效的類從metaspace卸載
6. 并發(fā)清除
? ??GC concurrent-cleanup-start /?GC concurrent-cleanup-end
? ? a. 清理RSet,包括card cache和code root table
? ? b. 當(dāng)區(qū)域完全清除后,添加到臨時隊列扒披,當(dāng)清除結(jié)束后值依,將臨時隊列合并到第二空閑區(qū)域隊列,等待被添加到主空閑隊列
當(dāng)并發(fā)標(biāo)記結(jié)束碟案,Young GC后會跟緊一個Mixed GC愿险。Mixed GC跟Young GC只有2點不同,如下:
1. 收集類型為混合的:?GC pause (G1 Evacuation Pause) (mixed)
2. CSet會包含通過并發(fā)標(biāo)記確定的老年區(qū)域
最后一種可能遇到的GC為Full GC价说,F(xiàn)ull GC是一個單線程的有STW的過程辆亏。
1. GC 產(chǎn)生原因,(Allocation Failure)鳖目。
2. Full GC的頻率
3. Full GC的消耗時間
加入‘-XX:+PrintGCApplicationStoppedTime’ and ‘-XX:+PrintGCApplicationConcurrentTime’配置產(chǎn)生的log
1. 業(yè)務(wù)線程在安全點停止的時間
2. 將所有線程帶到安全點并暫停的耗時
3. 業(yè)務(wù)線程在兩個安全點之間運行的時間
高級標(biāo)記(Advanced)
‘-XX:+PrintAdaptiveSizePolicy’:增加G1 ergonomics扮叨,便于對CSet選擇和暫停時間的估算有更深入的了解。
對于Young GC领迈,新增了如下log:
1. dirty card queue 有多少cards待處理彻磁,并預(yù)估時間
2. 該次收集有多少region參與,并預(yù)估時間惦费,并預(yù)估對象拷貝的時間
3. 最終CSet的選擇兵迅,并預(yù)估總時間抢韭,其實就是前兩部之和
4. 不一定出現(xiàn)薪贫。如果GC線程執(zhí)行時間/業(yè)務(wù)線程執(zhí)行時間大于某個閾值,G1會嘗試增大堆刻恭。不過我們的設(shè)置都是max=min瞧省,不會出現(xiàn)這個
5. 如果需要并發(fā)標(biāo)記會有這行l(wèi)og。
如果有并發(fā)階段鳍贾,會多打印如下log:
當(dāng)標(biāo)記結(jié)束鞍匾,緊著是mixed GC,多增如下log:
開始mixed GC的原因骑科,可回收的old區(qū)域>閾值橡淑。如果可回收的小于閾值,則不會開始咆爽。
Mixed GC開始:
1. 選擇CSet和為CSet添加young region跟Young GC一樣
2. 將Old Region添加到CSet梁棠。添加的old region的數(shù)量由參數(shù)XX:G1OldCSetRegionThresholdPercent=X控制,默認為10%
3. 總結(jié)CSet的情況斗埂,并預(yù)測總的暫停時間
4. 展示了Mixed GC循環(huán)的詳細信息符糊。由于釋放后,任然占堆的14%呛凶,大于閾值5%男娄,所以下一次垃圾回收還是Mixed
下一次Mixed垃圾回收跟上面的一致,但是結(jié)尾處有點區(qū)別:
1. 由于這次混合垃圾回收之后,old region的占比小于閾值模闲,故下次垃圾回收為young gc
最后建瘫,看一下Full GC的ergonomics
1. 在主從空閑隊列中均沒有空閑區(qū)域了,分配請求失敗围橡,需要請求堆擴展暖混。
2. 堆擴展請求。 但是1.2兩步中的操作還沒真正實施
3. 對擴展不會嘗試翁授,由于可用的未提交的regions數(shù)量為0拣播。由于擴展失敗,所以開始Full GC
4. 由于堆的最小值小于堆的最大值收擦,G1會在Full GC之后縮小堆的總量至70%
5. 堆縮小的詳細信息
-XX:+PrintTenuringDistribution 這個標(biāo)簽提供了survivor空間的分布
任期分布數(shù)據(jù)主要告訴我們survivor空間如下三點信息:
? ? a. The desired survivor size 就是survivor空間總量 乘以?TargetSurvivorRatio (默認值為 50%)
? ? b.?The target threshold 就是對象在Young GC時存活的歲數(shù)贮配。
? ? c. 年齡的分布,包括不同年齡對象的大小及增量的總和塞赂。
問題診斷標(biāo)記(Debug)
‘-XX:+G1PrintHeapRegions’:?
調(diào)試如下問題時有必要打印堆區(qū)事件:
? ? a. 調(diào)試尋找疏散失敗的原因及失敗區(qū)域的編號
? ? b. 確定巨型對象的大小和出現(xiàn)頻率
? ? c. 跟蹤和估算被規(guī)劃為CSet的Eden泪勒、Survivor和Old區(qū)的數(shù)量
1. COMMIT
? ? 堆的初始化或擴展完成,確定區(qū)域的頂和底
2.?ALLOC(Eden)
? ? 分配的Eden區(qū)域宴猾,由底的地址確定
3.?CSET
? ? CSet區(qū)域圆存,該區(qū)域?qū)⒈换厥眨傻椎牡刂反_定
4. CLEANUP
? ? 在并發(fā)標(biāo)記的時候完全被清空的區(qū)域仇哆,由底的地址確定
5.?UNCOMMIT
? ? 在Full GC后沦辙,如果堆被縮小,就會出現(xiàn)很多未提交的區(qū)域
6. ALLOC(Old)
????分配的Old區(qū)域讹剔,由底的地址確定? ??
7. RETIRE
? ? 在垃圾回收結(jié)束的時候油讯,最后一個被分配的Old區(qū)會被標(biāo)記為退休的
8. REUSE
? ? 下次一GC開始時,上一次退休的Old區(qū)會作為起始點
9. ALLOC(Survivor)
????分配的Survivor區(qū)域延欠,由底的地址確定?? ??
10.?EVAC-FAILURE
? ? 如果分配中出現(xiàn)疏散失敗陌兑,這里會指出失敗的區(qū)域
11.?POST-COMPACTION(Old)
? ? 在Full GC結(jié)束后,對有存活數(shù)據(jù)的Old和巨型數(shù)據(jù)區(qū)會進行壓縮
12.?ALLOC(SingleH)
????分配SingleH巨型數(shù)據(jù)區(qū)域由捎,對象只能占用一個區(qū)域
13.?ALLOC(StartsH)
? ? 分配StartsH巨型數(shù)據(jù)區(qū)兔综,對象可以放置在不止一個區(qū)域中
14.?ALLOC(ContinuesH)
? ? 分配ContinuesH巨型數(shù)據(jù)區(qū)
?‘-XX:+G1PrintRegionLivenessInfo’ 用于分析并發(fā)標(biāo)記后old區(qū)的分布:
其實就是翻譯了下這篇文章