分代收集演算法詳解

許佳佳233發表於2017-09-24

此篇文章較多借鑑《深入理解Java虛擬機器》

前提概要

這篇文章算是對前一篇文章的一個補充,主要地講一下涉及知識點較多的分代收集演算法。如果對Java垃圾回收演算法還不是很瞭解的讀者可以先看上一篇文章:Java垃圾回收演算法

分代收集概念

根據物件的存活週期不同將記憶體劃分為新生代和老年代,存活週期短的為新生代,存活週期長的為老年代。這樣就可以根據每塊記憶體的特點採用最適當的收集演算法。
新生代的中每次垃圾收集中會發現有大批物件死區,只有少量存活,那就選用複製演算法,只需要付出少量存活物件的複製成本就可以完成收集。
老年代中因為物件的存活率高,沒有額外的控制元件對它進行分配擔保,就必須使用“標記-清掃”或者“標記-整理”演算法來進行回收。

新生代中的複製演算法

根據複製演算法把新生代堆分為兩份,一份為使用區,一份為存活區。
使用區:存活區=8:1

每次新的物件都是在使用區建立,對使用區進行垃圾回收之後如果存活,就放入存活區。
新生代使用區和存活區的比例是8:1,所以很有可能新生代執行了複製回收演算法之後,存活區的記憶體不夠。這個時候,存活區無法容納的物件就會直接進入老年代。

物件如何進入老年代

1、大物件直接進入老年代
因為新生代是使用的複製演算法,所以要儘量減少複製的記憶體,所以物件記憶體到一定的值後就會直接進入老年代。

2、新生代物件年齡到一定程度後進入老年代
每個物件會有一個Age的計數器,初始值為0,每經過一次GC並且存活,這個物件的Age就會加1,如果增加到一定程度(預設為15)。那麼就會進入老年代中。

3、動態物件年齡判定
如果在新生代存活區中相同年齡所有物件大小的總和大於存活區的一半,年齡大於或等於該年齡的物件就會直接進入老年代。
比如現在存活區有三個物件,Age分別為2、2、3。那麼Age為3的這個物件就會進入老年代。

空間分配擔保

在新生代回收之前,虛擬機器首先會檢查老年代的最大可用連續空間是否大於新生代物件的總空間,如果是的,那麼就可以保證這次記憶體回收是安全的。(就是假設新生代的所有物件都會進入老年代)
如果上述不成立呢,就會檢視是否允許擔保失敗。

  • 如果允許失敗,那麼就不管夠不夠,還是啟動新生代的垃圾回收,當回收失敗時,就啟動老年代的垃圾回收,然後再重新執行新生代的垃圾回收。
  • 如果不允許失敗,那麼就會先啟動老年代的垃圾回收,然後再啟動新生代的垃圾回收。

相關文章