你的“對象”啥時候會進入老年代?

前言

JVM堆中有新生代老年代兩塊區域,因爲使用分代回收策略新生代還會劃分爲Eden和兩個Survivor區,JVM堆大概是這樣子:

程序運行過程中新產生的對象都會分配在Eden區,隨着時間的推移Eden區也是會滿的,那麼這個時候就會進行Minor GC進行清理,清理過程有的對象被清除,有的對象會繼續存活下去。那Java對象啥時候會進入老年代呢?

根據對象年齡

JVM會給對象增加一個年齡(age)的計數器,對象每“熬過”一次GC,年齡就要+1,待對象到達設置的閾值(默認爲15歲)就會被移移動到老年代,可通過-XX:MaxTenuringThreshold調整這個閾值。

一次Minor GC後,對象年齡就會+1,達到閾值的對象就移動到老年代,其他存活下來的對象會繼續保留在新生代中。

動態年齡判斷

根據對象年齡有另外一個策略也會讓對象進入老年代,不用等待15次GC之後進入老年代,他的大致規則就是,假如當前放對象的Survivor,一批對象的總大小大於這塊Survivor內存的50%,那麼大於這批對象年齡的對象,就可以直接進入老年代了。

如圖上的A、B、D、E這四個對象,假如Survivor 2是100m,如果A + B + D的內存大小超過50m,現在D的年齡是10,那E都會被移動到老年代。實際上這個計算邏輯是這樣的:年齡1 + 年齡2 + 年齡n的多個對象總和超過Survivor區的50%,那就會把年齡n以上的對象都放入老年代。

大對象直接進入老年代

如果設置了-XX:PretenureSizeThreshold這個參數,那麼如果你要創建的對象大於這個參數的值,比如分配一個超大的字節數組,此時就直接把這個大對象放入到老年代,不會經過新生代。

這麼做就可以避免大對象在新生代,屢次躲過GC,還得把他們來複制來複制去的,最後才進入老年代,這麼大的對象來回複製,是很耗費時間的。

歡迎大家關注公衆號:Java派一起交流學習Java、Android知識。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章