深入JVM:(五)記憶體分配與回收策略
一、物件優先在Eden分配
大多數情況下,物件在新生代Eden區中分配
。當Eden區沒有足夠空間進行分配時,虛擬機器將發起一次Minor GC。
新生代GC(Minor GC) 老年代GC(Major GC/Full GC)
二、大物件直接進入老年代
所謂的大物件是指,需要大量連續記憶體空間的Java物件,最典型的大物件就是那種很長的字串以及陣列(筆者列出的例子中的byte[]陣列就是典型的大物件)。大物件對虛擬機器的記憶體分配來說就是一個壞訊息(替Java虛擬機器抱怨一句,比遇到一個大物件更加壞的訊息就是遇到一群“朝生夕滅”的“短命大物件”,寫程式的時候應當避免)
虛擬機器提供了一個-XX:PretenureSizeThreshold
引數,令大於這個設定值的物件直接在老年代分配。這樣做的目的是避免在Eden區及兩個Survivor區之間發生大量的記憶體複製
三、長期存活的物件將進入老年代
虛擬機器給每個物件定義了一個物件年齡(Age)計數器。如果物件在Eden出生並經過第一次Minor GC後仍然存活,並且能被Survivor容納的話,將被移動到Survivor空間中,並且物件年齡設為1。物件在Survivor區中每“熬過”一次Minor GC,年齡就增加1歲,當它的年齡增加到一定程度(預設為15歲
),就將會被晉升到老年代中。物件晉升老年代的年齡閾值,可以通過引數-XX:MaxTenuringThreshold
設定。
四、動態物件年齡判定
虛擬機器並不是永遠地要求物件的年齡必須達到了MaxTenuringThreshold才能晉升老年代,如果在Survivor空間中相同年齡所有物件大小的總和大於Survivor空間的一半,年齡大於或等於該年齡的物件就可以直接進入老年代,無須等到MaxTenuringThreshold中要求的年齡。