JVM -- Full GC觸發條件總結以及解決策略


前言

Full GC相對於Minor GC來說,停止用戶線程的STW(stop the world)時間過長,至少慢10倍以上,所以要盡量避免,首先說一下Full GC可能產生的原因,接着給出排查方法以及解決策略。

 

1、System.gc()方法的調用

在代碼中調用System.gc()方法會建議JVM進行Full GC,但是注意這只是建議,JVM執行不執行是另外一回事兒,不過在大多數情況下會增加Full GC的次數,導致系統性能下降,一般建議不要手動進行此方法的調用,可以通過-XX:+ DisableExplicitGC來禁止RMI調用System.gc。

 

2、老年代(Tenured Gen)空間不足
       在Survivor區域的對象滿足晉升到老年代的條件時,晉升進入老年代的對象大小大於老年代的可用內存,這個時候會觸發Full GC。

 

3、Metaspace區內存達到閾值
       從JDK8開始,永久代(PermGen)的概念被廢棄掉了,取而代之的是一個稱為Metaspace的存儲空間。Metaspace使用的是本地內存,而不是堆內存,也就是說在默認情況下Metaspace的大小只與本地內存大小有關。-XX:MetaspaceSize=21810376B(約為20.8MB)超過這個值就會引發Full GC,這個值不是固定的,是會隨着JVM的運行進行動態調整的,與此相關的參數還有多個,詳細情況請參考這篇文章jdk8 Metaspace 調優

4、統計得到的Minor GC晉升到舊生代的平均大小大於老年代的剩余空間
Survivor區域對象晉升到老年代有兩種情況:

       一種是給每個對象定義一個對象計數器,如果對象在Eden區域出生,並且經過了第一次GC,那么就將他的年齡設置為1,在Survivor區域的對象每熬過一次GC,年齡計數器加一,等到到達默認值15時,就會被移動到老年代中,默認值可以通過-XX:MaxTenuringThreshold來設置。
       另外一種情況是如果JVM發現Survivor區域中的相同年齡的對象占到所有對象的一半以上時,就會將大於這個年齡的對象移動到老年代,在這批對象在統計后發現可以晉升到老年代,但是發現老年代沒有足夠的空間來放置這些對象,這就會引起Full GC。

5、堆中產生大對象超過閾值
       這個參數可以通過-XX:PretenureSizeThreshold進行設定,大對象或者長期存活的對象進入老年代,典型的大對象就是很長的字符串或者數組,它們在被創建后會直接進入老年代,雖然可能新生代中的Eden區域可以放置這個對象,在要放置的時候JVM如果發現老年代的空間不足時,會觸發GC。

6、老年代連續空間不足

       JVM如果判斷老年代沒有做足夠的連續空間來放置大對象,那么就會引起Full GC,例如老年代可用空間大小為200K,但不是連續的,連續內存只要100K,而晉升到老年代的對象大小為120K,由於120>100的連續空間,所以就會觸發Full GC。

 

7、CMS GC時出現promotion failed和concurrent mode failure
這個原因引發的Full GC可以參考這篇文章,下面也摘抄自這篇文章:JVM 調優 —— GC 長時間停頓問題及解決方法

       提升失敗(promotion failed),在 Minor GC 過程中,Survivor Unused 可能不足以容納 Eden 和另一個 Survivor 中的存活對象, 那么多余的將被移到老年代, 稱為過早提升(Premature Promotion)。 這會導致老年代中短期存活對象的增長, 可能會引發嚴重的性能問題。  再進一步, 如果老年代滿了, Minor GC 后會進行 Full GC, 這將導致遍歷整個堆, 稱為提升失敗(Promotion Failure)。


        在 CMS 啟動過程中,新生代提升速度過快,老年代收集速度趕不上新生代提升速度。在 CMS 啟動過程中,老年代碎片化嚴重,無法容納新生代提升上來的大對象,這是因為CMS采用標記清理,會產生連續空間不足的情況,這也是CMS的缺點

總結

可以發現其實堆內存的Full GC一般都是兩個原因引起的,要么是老年代內存過小,要么是老年代連續內存過小。無非是這兩點,而元數據區Metaspace引發的Full GC可能是閾值引起的,詳細原因還是建議參考其他文章,我就不誤人子弟了

 

 

原文鏈接:https://blog.csdn.net/Hollake/article/details/90484027


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM