1. 程式人生 > 其它 >JVM垃圾回收演算法的理解

JVM垃圾回收演算法的理解

GC判斷死亡物件的演算法:

  1. ​引用計數法
  2. 可達性分析演算法

JVM常用的垃圾回收演算法有以下幾種:

1. 標記清除演算法(年老代)
2. 標記複製演算法(年輕代)
3. 標記整理演算法(年老代)
4. 分代收集演算法

判斷物件死亡

引用計數法

​ 在物件中新增一個引用計數器,每當一個地方引用它的時候計數器加1;引用失效的時候計數器減1。當計數器為0時候就被回收。但是存在迴圈引用問題,如果一個物件對另外一個物件有依賴,造成多個物件迴圈依賴,依賴成環,那麼如果要回收A物件,就必須得釋放其他引用。然而其他引用是依賴於A的,所以最後誰也無法釋放。

可達性分析演算法

​ 通過GC Roots的物件作為起始點,從這些節點遍歷所有引用鏈,如果某個物件沒有GC Roots直接或間接連線,這個物件就可以被回收。

JVM常用的垃圾回收演算法

標記清除

​ 分為標記和清除兩個階段:標記出所有死亡的物件,然後把所有死亡的物件進行清除操作。

​ 缺點是造成記憶體碎片,後來的大物件無法儲存。造成記憶體使用率降低。

標記複製

​ 分為標記複製兩個階段。首先標記存活物件,完成後演算法把存活物件都複製到一塊新的記憶體空間裡去,然後把原來的記憶體空間情況。

​ 缺點是這個演算法需要很大的記憶體空間,因為要整體複製。

標記整理

​ 分為標記-整理-清除階段。首先標記存活的物件,將其整理到一邊,最後把存活邊界外的記憶體空間都清除一遍。

​ 好處是不會產生記憶體碎片,但是由於整理階段移動物件,所以需要更新物件的引用。

分代收集演算法

分代收集演算法將不同記憶體區域劃分,然後對不同性質的記憶體區域採取不同的以上的GC演算法,使優點變大,缺點削弱。

一般情況下將堆區劃分為老年代(Tenured Generation)和新生代(Young Generation),在堆區之外還有一個代就是永久代(Permanet Generation)。

在不同年代使用不同的演算法,從而使用最合適的演算法。

年輕代分為Eden和survivor區(from和to兩塊),且Eden : from : to==8:1:1

  1. 新產生的物件優先分配在Eden區,當Eden區滿了放不下了,其中存活的物件會被複制到from區。
  2. 之後物件繼續被分配在Eden裡,當Eden再次滿了,這時就會把Eden區和from區存活下來的物件複製到to區裡。(如果to區也放不下,則存活下來的物件全部進入老年代。)之後回收掉Eden和from區的所有記憶體。
  3. 向上面這樣物件會被複制很多次,預設複製了15此,就會進入老年代。當老年代滿了或者存放不下即將要進入老年代存活物件的時候,就會發生一次Full G。