JVM(五):Major、MinorGC簡述&&減少FullGC頻率


Java堆可以細分為:新生代和老年代;新生代又可細分為 Eden空間、From Survivor空間、To Survivor空間等

(Tenured space是老年代)

 

Minor GC:從年輕代空間(包括 Eden 和 Survivor 區域)回收內存被稱為 Minor GC。

Major GC 是清理老年代。

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

 

對象優先在Eden區分配:

    HotSpot JVM把年輕代分為了三部分:1個Eden區和2個Survivor區(分別叫from和to)。默認比例為8:1。大多數情況下,對象優先在Eden區中分配。當Eden區中沒有足夠空間進行分配時,將會觸發一次Minor GC。

大對象直接進入老年代:
    所謂的大對象是指,需要大量連續內存空間的Java對象。例如:很長的字符串或者數組。虛擬機提供了一個-XX:PretenureSizeThreshold參數。令大於這個-XX:PretenureSizeThreshold設置值的對象,直接在老年代分配。

長期存活的對象將進入老年代:
    虛擬機為了分代收集,對每一個對象定義了一個對象年齡計數器(Age)。如果對象在Eden出生,並且經過一次Minor GC后,仍然存活並且能被Survivor區中每熬過一次Minor GC,,年齡就會增加1歲。當年齡增加到默認的15歲時,就會晉升到老年代。

    晉升為老年代的闕值通過參數-XX:MaxTenuringThreshold設置。

許多 Major GC 是由 Minor GC 觸發的,所以很多情況下將這兩種 GC 分離是不太可能的。

這使得我們不用去關心到底是叫 Major GC 還是 Full GC,大家應該關注當前的 GC 是否停止了所有應用程序的線程,還是能夠並發的處理而不用停掉應用程序的線程

 

Full GC觸發條件:

(1)調用System.gc時,系統建議執行Full GC,但是不必然執行

(2)老年代空間不足——————比如連續大對象直接進入老年代

(3)方法區空間不足

(4)在執行minor gc的時候進行的一系列檢查

執行Minor GC的時候,JVM會檢查老年代中最大連續可用空間是否大於了當前新生代所有對象的總大小。
如果大於,則直接執行Minor GC(這個時候執行是沒有風險的)。
如果小於了,JVM會檢查是否開啟了空間分配擔保機制,如果沒有開啟則直接改為執行Full GC。
如果開啟了,則JVM會檢查老年代中最大連續可用空間是否大於了歷次晉升到老年代中的平均大小,如果小於則執行改為執行Full GC。--------
如果大於則會執行Minor GC,如果Minor GC執行失敗則會執行Full GC

 

簡而言之,

新生代所有對象總大小 〉 老年代可用空間  且沒有開啟空間分配擔保

歷次晉升到老年代 〉老年代可用

 

啥是空間分配擔保:

在發生Minor GC之前,虛擬機先檢查老年代最大可用的連續空間是否大於新生代所有對象總空間,如果條件成立的話,那么Minor GC確認是安全的;

如果不成立的話虛擬機就會檢查HandlePromotionFailure設置值是否允許擔保失敗,如果允許就會繼續檢查老年代最大可用的連續空間是否大於歷次晉升到老年代對象的平均大小,如果大於,將嘗試進行着一次Minor GC,盡管這次Minor GC是有風險的,可能觸發Full GC

如果小於或者HandlePromotionFailure設置不允許冒險,這時改為進行一次Full GC

 


免責聲明!

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



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