天天看點

Java虛拟機-記憶體配置設定政策

Java虛拟機-記憶體配置設定政策

Java技術體系中的自動記憶體管理可以歸結為自動化的解決了兩個問題:給對象配置設定記憶體和回收配置設定給對象的記憶體。前面講的是記憶體回收,這章講如何為對象配置設定記憶體。

一、記憶體配置設定政策概述

對象的記憶體分配置設定主要是指堆上配置設定(也可棧上配置設定),對象主要配置設定在新生代Eden區,如果啟動了本地線程配置設定緩沖,則按照線程優先在TLAB上配置設定。少數情況下也會直接配置設定在老年代,配置設定的規則不固定,取決于垃圾回收器組合以及JVM中與記憶體相關參數的設定。

我們以Serial/Serial Old收集器為例進行介紹。

二、記憶體配置設定政策

1.對象優先在Eden區配置設定

大多數情況下,對象在新生代的Eden區中配置設定,當Eden區沒有足夠空間進行配置設定時,虛拟機将會發起一次Minor GC。

2.大對象直接進入老年代

大對象是指需要大量連續記憶體空間的Java對象,典型大對象有長字元串和數組,大對象對虛拟機的記憶體配置設定來說是一個壞消息,寫程式時還要避免建立一些朝生夕死的短命大對象,經常出現大對象容易導緻記憶體還有不少空間時就提前觸發垃圾收集以擷取足夠的連續空間來安置他們。

虛拟機提供-XX:PretenureSizeThreshold參數,令大于這個設定值的對象直接在老年代配置設定,這樣避免再Eden及兩個Survivor區間發生大量的記憶體複制,這個參數隻對Serial和ParNew兩款收集器有效,如果遇到必須使用此參數的場合,可以考慮ParNew加CMS的組合。

大對象直接在老年代進行配置設定的目的是避免在Eden區和兩個Survivor區之間發生大量的記憶體複制。

3.根據對象年齡判定進入老年代

虛拟機給每個對象定義了一個對象年齡計數器,如果對象在Eden出生并經過第一次Minor GC後仍然存活,并且能被Survivor容納的話,将被移動到Survivor空間中,并且對象年齡設為1,對象在Survivor區中每熬過一次Minor GC,年齡就增加1歲,當它的年齡增加到一定程度(預設為15歲),就會被晉升到老年代中,可以通過-XX:MaxTenuringThreshold參數來設定年齡門檻值。

4.動态對象年齡判斷

為了能更好的适應不同程式的記憶體情況,虛拟機不是永遠的要求對象的年齡必須達到門檻值才能晉升老年代;如果在Survivor區中的相同年齡所有對象大小的總和大于Survivor空間的一半,年齡大于或者等于該年齡的對象就可以直接進入老年代,無須等到-XX:MaxTenuringThreshold 中要求的年齡。

5.空間配置設定擔保

關于配置設定擔保機制JDK6前後有差别的。  

JDK6之前

當發生Minor GC時,JVM會首先檢查老年代最大的可用連續空間是否大于新生代所有對象的總和,如果大于,那麼這次Minor GC是安全的,如果不大于的話,JVM就需要判斷HandlePromotionFailure是否允許空間配置設定擔保。

如果允許擔保失敗,那麼JVM會繼續檢查老年代最大的可用連續空間是否大于曆次晉升到老年代的對象的平均大小:

  • 如果大于,則正常進行一次YGC,盡管有風險(因為判斷的是平均大小,有可能這次的晉升對象比平均值大很多);
  • 如果小于,或者HandlePromotionFailure設定不允許空間配置設定擔保,這時要進行一次FGC。

對以上的步驟歸納一下,先看老年代的可用空間能否容下新生代的所有對象,不能的話看是否開啟了配置設定擔保機制,允許就先執行Minor GC,否則直接進行Full GC。大部分情況下還是會将HandlePromotionFailure開啟配置設定擔保,避免頻繁Full GC。

JDK6後

HandlePromotionFailure不再影響到虛拟機的空間配置設定擔保政策,變為隻要老年代的連續空間大于新生代對象總大小或曆次晉升的平均大小就會進行Minor GC,否則将進行Full GC。

三、概念充電

  • 新生代GC(Minor GC:縮寫YGC,指發生在新生代的垃圾回收動作,因為Java對象大多都具備朝生夕滅的特性,是以Monir GC非常頻繁,一般回收速度也比較快。
  • 老年代GC(Major GC/Full GC):指發生在老年代的GC,出現了Major GC,經常會伴随至少一次的Minor GC(但并非絕對的,在Parallel Scavenge)收集器的收集政策裡就有直接進行Major GC的政策選擇過程。Major GC的速度一般比Major GC慢10倍以上。
  1. ​​https://www.jianshu.com/p/bec8717d1952​​

繼續閱讀