1. 程式人生 > >深入理解java虛擬機器之自動記憶體管理機制(四)

深入理解java虛擬機器之自動記憶體管理機制(四)

記憶體分配與回收策略

(一)記憶體分配策略

    給誰分配?分配到哪?是記憶體分配策略必須解答的問題。

    java物件是分配的物件,往大方向來說,是分配到堆中,更細一點說,根據物件不同的特點分配到新生代和老年代區域。如果啟動了本地執行緒分配緩衝,就按執行緒優先在TLAB上分配。

    一、新生代區域的分配

       新創建出來的物件優先分配到新生代中的Eden區域。當Eden區域沒有足夠的空間時,會發生一次minor gc。當新生代總可用空間(Eden區+1個Survivor區的總容量)仍然
     不夠的時候,就通過空間分配擔保機制分到老年區。

       -Minor GC:發生在新生代的垃圾收集動作,非常頻繁,回收速度快。

       -Major GC / Full GC: 發生在老年代的垃圾收集動作,經常會伴隨至少一次的Minor GC。 速度一般比Minor GC慢10倍以上。

    二、老年代區域的分配

       進入老年代區域的物件有三種。

       1. 大物件直接進入。所謂大物件,是指需要大量連續記憶體空間的java物件。虛擬機器提供了一個 -XX:PretenureSizeThreshold引數,令空間大於這個設定值的物件直接在老年代

        分配。這樣做的目的是避免在Eden區及兩個Survivor之間發生大量的記憶體複製。

       2. 長期存活的物件。老年代,顧名思義,裡面應該存放著“老”物件。如何判斷一個物件老不老呢?虛擬機器給每個物件定義了一個物件年齡計數器。如果物件出生在Eden並經過
        第一次Minor GC後任然能夠存活,並且能夠被Survivor容納的話,將被移動到Survivor空間中,並且物件年齡設為1。在Survivor中的物件每熬過一次Minor GC,年齡就增加
        1歲。當物件的年齡增加到一定程度(預設15歲),就會晉升到老年代中。這個年齡閾值可以通過-XX:MaxTenuringThreshold設定。

       3. 動態物件年齡判定下的物件。如果在Survivor空間中相同年齡所有物件大小的總和大於Survivor空間的一半,那麼年齡>=該年齡的物件將直接進入老年代。

     三、空間分配擔保

       在發生Minor GC之前,虛擬機器先檢查老年代最大可用連續空間是否大於新生代所有物件的總和,是,那Minor GC就是安全的;否,虛擬機器就檢視HandlePromotionFailure設定
     值是否允許擔保失敗。允許,就繼續檢視老年代最大可用連續空間是否大於歷次晉升到老年代物件的平均大小,成立,就嘗試進行Minor GC;不成立,或者HandlePromotionFailure
     不允許,就要改為進行一次Full GC。