java垃圾回收之複製演算法
之前的java垃圾回收演算法之-標記清除 會導致記憶體碎片。下文的介紹的coping演算法可以解決記憶體碎片問題。
概述
如果jvm使用了coping演算法,一開始就會將可用記憶體分為兩塊,from域和to域, 每次只是使用from域,to域則空閒著。當from域記憶體不夠了,開始執行GC操作,這個時候,會把from域存活的物件拷貝到to域,然後直接把from域進行記憶體清理。
應用場景
coping演算法一般是使用在新生代中,因為新生代中的物件一般都是朝生夕死的,存活物件的數量並不多,這樣使用coping演算法進行拷貝時效率比較高。
jvm將Heap 記憶體劃分為新生代與老年代,又將新生代劃分為Eden(伊甸園) 與2塊Survivor Space(倖存者區) ,然後在Eden –>Survivor Space 以及From Survivor Space 與To Survivor Space 之間實行Copying 演算法。 不過jvm在應用coping演算法時,並不是把記憶體按照1:1來劃分的,這樣太浪費記憶體空間了。一般的jvm都是8:1。也即是說,Eden區:From區:To區域的比例是
8:1:1
始終有90%的空間是可以用來建立物件的,而剩下的10%用來存放回收後存活的物件。
1、當Eden區滿的時候,會觸發第一次young gc,把還活著的物件拷貝到Survivor From區;當Eden區再次觸發young gc的時候,會掃描Eden區和From區域,對兩個區域進行垃圾回收,經過這次回收後還存活的物件,則直接複製到To區域,並將Eden和From區域清空。
2、當後續Eden又發生young gc的時候,會對Eden和To區域進行垃圾回收,存活的物件複製到From區域,並將Eden和To區域清空。
3、可見部分物件會在From和To區域中複製來複制去,如此交換15次(由JVM引數MaxTenuringThreshold決定,這個引數預設是15
注意:
萬一存活物件數量比較多,那麼To域的記憶體可能不夠存放,這個時候會藉助老年代的空間。
- 1
優點
在存活物件不多的情況下,效能高,能解決記憶體碎片和java垃圾回收演算法之-標記清除 中導致的引用更新問題。
缺點
- 會造成一部分的記憶體浪費。不過可以根據實際情況,將記憶體塊大小比例適當調整;
- 如果存活物件的數量比較大,coping的效能會變得很差。