文章目錄
- 記憶體配置設定與回收政策
-
- 對象優先在 Eden 配置設定
- 大對象直接進入老年代
- 長期存活的對象将進入老年代
- 動态對象年齡判定
- 空間配置設定擔保
記憶體配置設定與回收政策
Java 體系中所提倡的自動記憶體管理最終可以歸結為自動化地解決了兩個問題:給對象配置設定記憶體以及回收配置設定給對象的記憶體。
對象的記憶體配置設定,往大方向講就是在堆上配置設定,對象主要配置設定在新生代的 Eden 區上,如果啟動了本地線程配置設定緩沖,将按線程優先在 TLAB 上配置設定。少數情況下也可能直接配置設定到老年代,配置設定的規則取決于使用哪一種垃圾收集器組合以及虛拟機中與記憶體相關的參數設定。
介紹一下兩種 GC:
- 新生代 GC(Minor GC):指發生在新生代的垃圾回收動作,因為 Java 對象大多由具備朝生夕滅的特性,是以 Minor GC 非常頻繁,一般回收速度也比較快。
- 老年代 GC(Major GC / Full GC):指發生在老年代的 GC,出現了 Major GC,經常會伴随着至少一次的 Minor GC(非絕對)。Major GC 的速度一般會比 Minor GC 慢10倍以上。
對象優先在 Eden 配置設定
大多數情況下,對象在新生代 Eden 區中配置設定。當 Eden 區中沒有足夠空間進行配置設定時,虛拟機将發起一次 Minor GC。
虛拟機提供了 -XX:+PrintGCDetails 這個收集器日志參數,可以列印回收日志。
大對象直接進入老年代
大對象指的是需要大量連續記憶體的 Java 對象,如數組等。虛拟機提供了一個 -XX:PretenureSizeThreshold 參數(隻對 Serial 和 ParNew 收集器有效,Parallel Scavenge 收集器不認識這個參數也不需要配置),令大于這個設定值的對象直接在老年代配置設定。這樣做的目的是避免在 Eden 區及兩個 Survivor 區之間發生大量的記憶體複制(新生代采用複制算法收集記憶體)。
長期存活的對象将進入老年代
虛拟機采用分代收集的思想來管理記憶體,那麼記憶體回收時就要識别哪些對象應放在新生代,哪些應放在老年代。為做到這點,虛拟機給每個對象定義了一個對象年齡(Age)計數器。如果對象在 Eden 出生并經過第一次 Minor GC 後仍然存活,并且能夠被 Survivor 容納的話,将被移動到 Survivor 空間中,并将年齡設定為 1.對象在 Survivor 區中每“熬過”一次 Minor GC,年齡就增加 1 歲,當年齡增加到一定程度(預設為 15 歲)是,就會被晉升到老年代中。可以通過參數 -XX:MaxTenuringThreshold 設定。
動态對象年齡判定
為适應不同程式記憶體情況,虛拟機并不是永遠要求對象年齡必須達到了 MaxTenuringThreshold 才能晉升到老年代,如果在 Survivor 空間中相同年齡所有對象大小的總和大于 Survivor 空間的一半,年齡大于等于該年齡的對象就可直接進入老年代,無須等到 MaxTenuringThreshold 中要求的年齡。
空間配置設定擔保
在發生 Minor GC 之前,虛拟機會先檢查老年代最大可用連續空間是否大于新生代所有對象總空間,如果這個條件成立,那麼 Minor GC 可以確定是安全的。如果不成立,則虛拟機會繼續檢查老年代最大可用的連續空間是否大于曆次晉升到老年代對象的平均大小,如果大于,将嘗試着進行一次 Minor GC,盡管這次 Minor GC 是有風險的;如果小于則會進行一次 Full GC。