1. 程式人生 > >讀薄《深入理解 JAVA 虛擬機器》Java記憶體分配策略

讀薄《深入理解 JAVA 虛擬機器》Java記憶體分配策略

記憶體分配規則不是固定的,取決於當前使用的是哪一種垃圾收集器以及虛擬機器配置。

物件優先在 Eden 上分配

大多數情況下,物件分配在 Eden 上,當記憶體不足的時候觸發一次 Minor GC。

大物件分配進老年代

需要連續記憶體空間的物件,最典型的是很長的字串已經陣列,寫程式的時候應該避免生命週期短的大物件。經常出現大物件記憶體不足以存放而提前出發 GC 的情況。

虛擬機器提供了一個引數 -XX:PretenureSizeThreshold 引數,當大於這個引數設定值的物件的時候直接在老年代分配。

長期存活物件進入老年代

虛擬機器給每一個物件都有一個年齡計數器,當每一次 GC 後,被保留下來的物件的年齡就加一。

當年齡達到一定程度,就會晉升到老年代。

可以通過引數 -XX:MaxTenuringThreshold 來設定晉升老年代的閾值。

動態物件年齡判定

為了更好適應虛擬機器環境,如果在 survivor 空間中所有相同年齡物件總和大於 Survivor 空間一半,則這些物件都直接進入老年代。

空間擔保分配

當發生 Minor GC 之前,虛擬機器會檢查老年代最大可用空間是否大於新生代所有的物件的空間,如果大於,則這次 GC 是安全的,直接進行 GC。如果小於,則會去檢視 HandlePromotionFailure 設定值是否允許擔保失敗。如果允許,則會去檢視最近 GC 完物件剩餘平均值,如果剩餘平均值小於老年代可以用來擔保的空間,則進行一次有風險的 Minor GC。否則就進行一次 Full GC。

如果不允許冒險,則直接進行 Full GC。

但是這個引數在 JDK 24 後就不再使用,如果老年代大於平均值則直接 Minor GC。