G1
調(diào)優(yōu)場景
Evacuation Failure
"evacuation failure", "to-space exhausted", "to-space overflow"古话, "promotion failure"之類的字眼舷夺。這些術(shù)語的概念在G1 GC是相似的
巨型對象和巨型對象分配
對于 G1 GC缩抡,任何超過區(qū)域一半大小的對象都被視為“巨型對象”。此類對象直接被分配到老年代中的“巨型區(qū)域”挤巡。這些巨型區(qū)域是一個連續(xù)的區(qū)域集。StartsHumongous 標(biāo)記該連續(xù)集的開始准谚,ContinuesHumongous 標(biāo)記它的延續(xù)积暖。
在分配任何巨型區(qū)域之前,會檢查標(biāo)記閾值孙咪,如有必要堪唐,還會啟動一個并發(fā)周期。
在清理階段或完整的垃圾回收周期內(nèi)翎蹈,標(biāo)記周期結(jié)束時會清理死亡的巨型對象淮菠。
為了減少復(fù)制開銷,巨型對象未包括在疏散暫停中荤堪。完整的垃圾回收周期會對巨型對象進(jìn)行壓縮合陵。
由于每個 StartsHumongous 和 ContinuesHumongous 區(qū)域集只包含一個巨型對象,所以沒有使用巨型對象的終點(diǎn)與上個區(qū)域的終點(diǎn)之間的空間(即巨型對象所跨的空間)澄阳。如果對象只是略大于堆區(qū)域大小的倍數(shù)拥知,則此類未使用的空間可能會導(dǎo)致堆碎片化。
如果巨型分配導(dǎo)致連續(xù)的并發(fā)周期碎赢,并且此類分配導(dǎo)致老年代碎片化低剔,請增加 -XX:G1HeapRegionSize,這樣一來肮塞,之前的巨型對象就不再是巨型對象了襟齿,而是采用常規(guī)的分配路徑。
當(dāng)未找到能放下巨型對象的連續(xù)分區(qū)時枕赵,G1會首先嘗試擴(kuò)展堆空間猜欺,擴(kuò)展失敗時,啟動串行g(shù)ull gc拷窜。
引用處理
-XX:PrintReferenceGC在GC日志中輸出各種引用詳細(xì)GC數(shù)據(jù)开皿。
通常钓试,在G1年輕代或者混合收集中,當(dāng)PrintGCDetails輸出中的Ref Proc時間超過GC暫停時間總數(shù)的10%時副瀑,需要進(jìn)行調(diào)優(yōu):
1.-XX:+ParalleRefProcEnabled激活多線程引用處理,負(fù)面影響是會搶占用戶線程時間片恋谭。
2.第一點(diǎn)作用不明顯時糠睡,觀察GC日志,找到導(dǎo)致Ref Proc處理時間過長的引用類型疚颊,優(yōu)化應(yīng)用程序減少對該類型引用的使用狈孔。
軟引用特別說明:
由于軟引用對象只會在OOM前回收,所以軟引用對象可能會長期占用內(nèi)存而頻繁觸發(fā)老年代收集周期材义,使用-XX:SoftRefLRUPolicyMSPerMB可以控制軟引用對象回收時機(jī)均抽,
回收周期
年輕代GC
對象從eden區(qū)分配失敗時觸發(fā),copy eden + from survivor -> to survivor其掂,超過晉升閾值的對象copy到老年代油挥。
-
-XX:MaxGCPauseMillis 200ms
JVM會根據(jù)該參數(shù)調(diào)整年輕代大小。如果用戶設(shè)置了-Xmn或者-XX:NewRatio等年輕代空間調(diào)整參數(shù)款熬,會導(dǎo)致暫停目前參數(shù)失效深寥。
-XX:G1NewSizePercent 5%
-XX:G1MaxNewSizePercent 60%
-XX:MaxTenuringThreshold 15
混合GC
觸發(fā)時機(jī):
當(dāng)老年代分區(qū)占用總堆比例超過閾值(默認(rèn)45%)時,觸發(fā)混合GC贤牛。
初始標(biāo)記:和下一次年輕代GC一起惋鹅,STW并行標(biāo)記,收集所有的GC Roots殉簸。
并發(fā)標(biāo)記:多線程并發(fā)協(xié)同標(biāo)示存活對象圖闰集。
重新標(biāo)記:STW并行重新標(biāo)記上個階段產(chǎn)生的新垃圾。
并行回收:垃圾清理般卑。
-
-XX:ConGCThreads
設(shè)置并行標(biāo)記的線程數(shù)武鲁。默認(rèn)值為并行垃圾回收線程數(shù) (ParallelGCThreads) 的 1/4 。
增大該值將會占用應(yīng)用線程處理時間椭微,降低吞吐量洞坑,因?yàn)椴l(fā)GC線程和應(yīng)用線程同時工作。
-
初始標(biāo)記
借道年輕代的STW執(zhí)行蝇率,標(biāo)記出GC Roots直接可達(dá)的對象迟杂,將NTAMS置到分區(qū)頂部。
- -XX:InitiatingHeapOccupancyPercent IHOP 45%
老年代占用比例超過該值時觸發(fā)并發(fā)標(biāo)記周期本慕。
-
根分區(qū)掃描
年輕代存活對象作為“根分區(qū)”排拷,掃描“根分區(qū)”對老年代的引用。
-
并發(fā)標(biāo)記周期
使用基于寫前柵欄的SATB快照標(biāo)記算法(應(yīng)用線程將發(fā)生更改前的引用放入stab_queue锅尘,由并發(fā)標(biāo)記線程定期處理监氢,以此找到標(biāo)記開始時刻的存活對象快照)布蔗,在多個并發(fā)標(biāo)記周期不斷交換PTAMS和NTAMS完成標(biāo)記。
http://www.reibang.com/p/9e70097807ba
-
重新標(biāo)記
STW浪腐,GC線程并行處理所有生效的SATB緩沖區(qū)及所有更新(Rset更新纵揍?)。處理引用议街。
-
清除
識別所有空閑分區(qū)泽谨,清理空閑分區(qū)RSet,釋放到空閑隊列特漩;
整理堆分區(qū)吧雹,為混合垃圾回收識別出高效率的老年代分區(qū);
RSet梳理(比如涂身,標(biāo)記過程發(fā)現(xiàn)RSet中記錄的某個對象已經(jīng)死亡雄卷,將該記錄從RSet中刪除)。
高效率的分區(qū):
1.存活對象少蛤售。
2.對象被別的分區(qū)對象引用數(shù)量少丁鹉。這里數(shù)量多會導(dǎo)致RSet中PRT粒度粗化,增大RSet掃描開銷悴能。
交換位圖鳄炉、指針?并發(fā)標(biāo)記周期也交換搜骡?
-
混合回收
-
-XX:G1MixedGCLiveThresholdPercent 85%
old generation region 中的存活對象的占比拂盯,低于該值時才會被選入 CSet。
-
-XX:G1MixedGCCountTarget 8
設(shè)置標(biāo)記周期完成后记靡,對存活數(shù)據(jù)上限為 G1MixedGCLIveThresholdPercent 的舊區(qū)域執(zhí)行混合垃圾回收的目標(biāo)次數(shù)谈竿。默認(rèn)值是 8 次混合垃圾回收∶停混合回收的目標(biāo)是要控制在此目標(biāo)次數(shù)以內(nèi)空凸。
-
每次混合收集老年代CSet的最小數(shù)量 = 混合收集周期將回收的候選老年代分區(qū)總數(shù)/G1MixedGCCountTarge
- -XX:G1HeapWastePercent 10%
混合收集周期中發(fā)現(xiàn)垃圾占總堆比例低于該值時,停止混合收集周期
- -XX:G1OldCSetRegionThresholdPercent 10%
每次混合收集暫停收集分區(qū)上限寸痢,默認(rèn)總堆的10%
Full GC
觸發(fā)時機(jī):對象分配失敗時呀洲?
使用串行垃圾收集器對整個堆全面壓縮。
G1的設(shè)計目標(biāo)通過不斷調(diào)優(yōu)而不再需要full GC啼止。
公共
-
-XX:G1HeapRegionSize
超過該值50%的對象將被視為巨型對象道逗,直接分配在老年代。JDK 8u40之前献烦,巨型對象由混合GC并發(fā)收集周期的清除階段回收滓窍,之后可以在年輕代GC回收。
1MB~32MB巩那,G1默認(rèn)將堆劃為為約2048個Region吏夯。
-
-XX:G1ReservePercent=10
設(shè)置作為空閑空間的預(yù)留內(nèi)存百分比此蜈,以降低目標(biāo)空間溢出的風(fēng)險。默認(rèn)值是 10%噪生。增加或減少百分比時裆赵,請確保對總的 Java 堆調(diào)整相同的量。
copy對象到to-space時產(chǎn)生對象晉升跺嗽,老年代空間不足時會擴(kuò)展老年代堆空間顾瞪,老年代空間已達(dá)上限會產(chǎn)生晉升失敗,增大預(yù)留內(nèi)存占比可避免晉升失敗抛蚁。
-
-XX:ParallelGCThreads
設(shè)置 STW 工作線程數(shù)的值。將 n 的值設(shè)置為邏輯處理器的數(shù)量惕橙。n 的值與邏輯處理器的數(shù)量相同瞧甩,最多為 8。
如果邏輯處理器不止八個弥鹦,則將 n 的值設(shè)置為邏輯處理器數(shù)的 5/8 左右肚逸。這適用于大多數(shù)情況,除非是較大的 SPARC 系統(tǒng)彬坏,其中 n 的值可以是邏輯處理器數(shù)的 5/16 左右朦促。
堆空間調(diào)整
JVM通過在Xms和Xmx之間動態(tài)調(diào)整堆大小及年輕代大小,以滿足用戶設(shè)置的GC暫停時間MaxGCPauseMillis和GCTimeRatio(用戶線程時間/GC線程時間)的目標(biāo)栓始。
RSet
引用關(guān)系
PRT 粒度务冕?
關(guān)系維護(hù)
維護(hù)時機(jī):
對象引用關(guān)系變化時(包括引用賦值、GC移動對象等)幻赚,觸發(fā)寫柵欄代碼禀忆,維護(hù)Rset。
若發(fā)生一個跨區(qū)引用關(guān)系變化落恼,G1垃圾收集器會將相應(yīng)的card加入到“臟卡片隊列”箩退。“并發(fā)優(yōu)化線程”會掃描隊列中的卡片來更新RSet佳谦。當(dāng)“并發(fā)優(yōu)化線程”來不及處理不過來時戴涝,會掛起用戶線程,讓用戶線程也加入到更新Rset钻蔑。
全局卡片表
在任意收集周期啥刻,掃描Rset與PRT時,會將掃描到的引用記錄標(biāo)記到全局卡片表咪笑,避免重復(fù)掃描郑什。在收集周期的最后將該表清空,顯示為Clear CT蒲肋。
工作竊取機(jī)制
收集活動圖
活動流程
關(guān)鍵算法
http://www.reibang.com/p/548c67aa1bc0
RSET
-
寫后柵欄
http://www.reibang.com/p/870abddaba41
- 并發(fā)優(yōu)化線程
-
寫前柵欄
年輕代收集
如何確保新生代對象被老年代引用的時候不被gc蘑拯?(查詢老年代對象來確認(rèn)對新生代對象的引用避免誤回收)
機(jī)制:當(dāng)老年代存活對象多時钝满,每次minor gc查詢老年代所有對象影響gc效率(因?yàn)間c stop-the-world),所以在老年代有一個write barrier(寫屏障)來管理的card table(卡表)申窘,card table存放了所有老年代對象對新生代對象的引用弯蚜。
所以每次minor gc通過查詢card table來避免查詢整個老年代,以此來提高gc性能剃法。
初始標(biāo)記
并發(fā)標(biāo)記周期
混合收集周期
GC日志
跑出完成GC日志碎捺,標(biāo)記日志說明。
http://www.reibang.com/p/ac1ba3479c08
引用
堆外內(nèi)存回收
http://www.reibang.com/p/35cf0f348275
Reference&ReferenceQueue
http://www.reibang.com/p/f0da6c1af815