1 對象優先在Eden區中配置設定
目前主流的垃圾收集器都會采用分代回收算法,是以需要将堆記憶體分為新生代和老年代.
在新生代中為了防止記憶體碎片,垃圾收集器一般都選用”複制”算法.是以,堆記憶體的新生代被進一步分為:Eden區+Survior1區+Survior2區.
每次建立對象時,首先會在Eden區中配置設定.
若Eden區已滿,則在Survior1區中配置設定.
若Eden區+Survior1區剩餘記憶體太少,導緻對象無法放入該區域時,就會啟用”配置設定擔保”,将目前Eden區+Survior1區中的對象轉移到老年代中,然後再将新對象存入Eden區.
2 大對象直接進入老年代
所謂”大對象”就是指一個占用大量連續記憶體空間的對象,如很長的字元串及數組.
當發現一個大對象在Eden區+Survior1區中存不下的時候就需要配置設定擔保機制把目前Eden區+Survior1區的所有對象都複制到老年代中去.
一個大對象能夠存入Eden區+Survior1區的機率比較小,發生配置設定擔保的機率比較大,而配置設定擔保需要涉及到大量的複制,就會造成效率低下.
是以,對于大對象我們直接把他放到老年代中去,進而就能避免大量的複制操作.
那麼,什麼樣的對象才是”大對象”呢?
-
-XX:PretrnureSizeThreshold參數
該參數用于設定大小超過該參數的對象被認為是”大對象”,直接配置設定在老年代.
注意:該參數隻對Serial和ParNew收集器有效.
3 生命周期較長的對象進入老年代
老年代用于存儲生命周期較長的對象,那麼我們如何判斷一個對象的年齡呢?
新生代中的每個對象都有一個年齡計數器,當新生代發生一次MinorGC後,存活下來的被移動到Survivor空間的對象的年齡就加一,在Survivor區每熬過一次MinorGC,年齡就加一,當年齡超過一定值(預設15)時,就将該對象轉移到老年代中.
-
-XXMaxTenuringThreshold參數
設定該參數後,隻要超過該參數的新生代對象都會被轉移到老年代中.
4 對象年齡的動态判定
在Survivor空間中,如果年齡相同的對象的記憶體大小總和超過了Survivor空間的一半,那麼所有年齡相同的對象和超過該年齡的對象都會被轉移到老年代中.無須等到MaxTenuringThreshold要求的年齡.
5 “配置設定擔保”政策詳解
在發生MinorGC前,JVM首先會檢查老年代中最大可用的的連續空間是否大于新生代中所有對象的大小.若此條件
- 成立,那麼MinorGC可以確定安全進行.
- 不成立,JVM會檢視HandlePromotionFailure設定值是否允許擔保失敗.若允許,繼續檢查老年代最大可用的連續空間是否大于曆次晉升到老年代對象的平均大小
-
-
-
- 若大于,将嘗試一次MinorGC,雖然此次MinorGC是有風險的.
- 若小于或HandlePromotionFailure設定不允許冒險,則進行一次FullGC.通過清除老年代中廢棄資料來擴大老年代空閑空間,以便給新生代作擔保.
-
-
注意:
1. 配置設定擔保是老年代為新生代作擔保.
2. 新生代中使用”複制”算法實作垃圾回收,老年代中使用’标記-清除”或”标記-整理”算法實作垃圾回收,隻有使用”複制”算法的區域才需要配置設定擔保,是以新生代需要配置設定擔保,而老年代不需要配置設定擔保.