天天看點

JVM------垃圾收集算法詳解

JVM的垃圾收集算法主要分為以下方面:

1、标記-清除算法

标記-清除算法分為标記和清除兩個階段:首先标記出所需要回收的對象,在标記完成後統一回收所有被标記的對象。

不足:一個是效率問題,标記和清除兩個過程的效率都不高;另一個是空間問題,标記清除之後會産生大量不連續的記憶體碎片,空間碎片太多可能會導緻以後程式運作過程中需要配置設定較大對象時,無法找到足夠的連續記憶體而不得不提前觸發另一次垃圾收集

2、複制算法(新生代回收的算法)

複制算法是為了解決”标記清除“的效率問題。它将可用的記憶體劃分為兩個大小相等的記憶體。每次隻是用其中的一塊。當這塊記憶體需要進行垃圾回收時,會将此區域還存活的對象複制到另一塊上面,然後把已經使用的記憶體區域一次清理掉。

優點:每次都對整個半區進行垃圾回收,記憶體配置設定的時候不需要考慮記憶體碎片等情況

不足:對象存活率較高時,會進行較多的複制操作,效率變低。浪費了50%的空間

現在的商用虛拟機(包括HotSpot)都是采用這種收集算法來回收新生代

新生代中98%的對象都是朝生夕死的,是以用複制算法。并且并不需要1:1的比例劃分空間,而是将新生代記憶體劃分為一個較大的的Eden空間和兩塊較小的Survivor空間(一個是from區一個是to區),每次使用Eden空間和其中一塊Survivor。當回收的時候,将Eden和Survivior還存活的對象一次複制到另外一塊survivor空間上,最後清理掉eden和survivor用過的空間。HotSpot虛拟機預設Eden和兩個Survivor的大小比例是8:1:1。當Survivor的空間不足以放下Eden和Survivor的存活的對象,那麼就用老年代的空間進行配置設定擔保

3、标記-整理算法(老年代回收算法)

針對老年代的特點,提出了老年代回收算法。首先也是将要回收的對象标記出來,再把存活的對象移向一端,然後清理掉端邊界以外的記憶體。

4、分代收集算法

目前商業虛拟機的垃圾收集都采用“分代收集算法”,根據對象存活周期的不同将java堆劃分為新生代和老年代。

新生代中,每次垃圾收集都會有大量對象死去,隻有少量存活,是以就用複制算法,隻需要付出少量存活對象的複制成本就可以完成收集。

老年代中,對象的存活率高,使用垃圾清理或者垃圾整理算法進行回收

HotPot實作的複制算法流程如下:

1、當Eden區滿的時候,會觸發第一次Minor gc,把還存活的對象拷貝到Survivor from區;當Eden區再次觸發minor gc的時候,會掃描Eden區和from區,對兩個區域進行垃圾回收,把存活的對象直接複制到To區域,并将Eden和From區域清空。

2、當後續的Eden去又發生Minor gc的時候,會對Eden區和To區域進行垃圾回收,存活的對象複制到From區域,并将Eden和To區域清空

3、部分對象會在From區和To區中來回複制,如此交換15次(由jvm參數設定),最終如果還存活,就進入老年代