1. 程式人生 > >Java虛擬機器:記憶體分配策略

Java虛擬機器:記憶體分配策略

  Java中提倡的自動記憶體管理機制最終可以歸結為自動化的解決兩個問題:給物件分配記憶體和回收分配給物件的記憶體。在之前的部落格中已經詳細講解了記憶體回收體系及原理,下面我們來探討給物件分配記憶體那些事兒。

       物件的記憶體分配,總體上講就是在堆上分配,物件主要分配在新生代的Eden區,少數情況也會直接分配在老年代。分配的規則並不是百分百固定的,其細節取決於當前使用的是哪一種垃圾收集器組合,還有虛擬機器中與記憶體相關的引數配置。

       物件優先在Eden區分配

       大多數情況下,物件在新生代Eden區分配。當Eden區沒有足夠空間進行分配時,虛擬機器會觸發一次Minor GC,Minor GC採用複製演算法進行垃圾回收。

       大物件直接進入老年代

       所謂大物件,是指需要大量連續記憶體的Java物件,最典型的大物件就是那種很長的字串以及陣列。大物件對虛擬機器記憶體分配來說就是壞訊息,經常會出現大物件在記憶體還有不少空間時就提前觸發一次垃圾回收以獲取足夠的連續記憶體空間來安置它們。

       那麼多“大”的物件算大物件呢?虛擬機器提供了一個 -XX:PretenureSizeThreshold引數,大於這個引數值的物件直接進入老年代。這樣做的目的是避免在Eden區以及兩個Survivor區之間發生大量的物件複製(新生代採用複製演算法回收記憶體)。

       長期存活的物件進入老年代

       由於虛擬機器採用了分代收集演算法來回收記憶體,那麼記憶體收集時就必須識別哪些物件應該放在新生代,哪些物件應該放在老年代中。為了做到這一點,虛擬機器給每個物件定義了一個年齡計數器,年齡值存放在在物件的header中。如果物件在Eden出生並經過第一次Minor GC後仍然存活下來,並且能被Survivor區容納的話,將被移動到Survivor區中,並且將物件的年齡值設為1。物件在Survivor區中每熬過一次Minor GC,年齡就增加1歲,當它的年齡增加到一定程度(預設15歲),就會被移到老年代中。物件晉升老年代的年齡閥值可以通過引數 -XX:MaxTenuringThreshold設定。

       順便提一下,虛擬機器也並不是永遠要求物件的年齡必須達到了MaxTenuringThreshold引數值才能晉升老年代,如果在Survivor空間中相同年齡所有物件大小的總和大於Survivor空間的一半,那麼年齡值大於或等於該年齡的所有物件就可以直接進入老年代,無須等到MaxTenuringThreashold引數要求的年齡。

轉載 https://www.cnblogs.com/fangfuhai/p/7208919.html