第四篇內(nèi)容,我們分享了如何判定一個(gè)對(duì)象是否存活,以及對(duì)象的二次逃脫,本節(jié)就在上一篇的基礎(chǔ)上,講解內(nèi)存的回收算法。
回收算法
1. 標(biāo)記——清楚算法
算法思路:
分為“標(biāo)記”和“清除”兩個(gè)階段:首先標(biāo)記處所有需要回收的對(duì)象,在標(biāo)記萬恒后統(tǒng)一回收被標(biāo)記的對(duì)象
缺點(diǎn):
a. 效率低
b. 會(huì)產(chǎn)生大量內(nèi)存碎片

2、復(fù)制算法
算法思路:
它將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只用其中一塊,當(dāng)這一塊內(nèi)存用完了,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已經(jīng)使用過的內(nèi)存空間一次性清理掉。
這樣每次只需要對(duì)整個(gè)半?yún)^(qū)進(jìn)行內(nèi)存回收,內(nèi)存分配時(shí)也不需要考慮內(nèi)存碎片等復(fù)雜情況,只需要移動(dòng)堆頂指針,按照順序分配即可。復(fù)制算法的執(zhí)行過程如圖:

缺點(diǎn):
a. 效率也比較低,比如在對(duì)象存活率較高的場景下要進(jìn)行大量的復(fù)制操作,當(dāng)然如果極端情況,比如對(duì)象100%存活的情況下,還需要額外的空間進(jìn)行分配擔(dān)保
b. 耗費(fèi)內(nèi)存空間
3、標(biāo)記-整理算法
算法思路:
根據(jù)老年代的特點(diǎn),有人提出了另外一種標(biāo)記-整理算法,過程與標(biāo)記-清除算法一樣,不過不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活對(duì)象都向一端移動(dòng),然后直接清理掉邊界以外的內(nèi)存。標(biāo)記-整理算法的工作過程如圖:

4、分代收集算法
算法思路:
作為現(xiàn)代商用虛擬機(jī)基本都采用的“算法”,與其稱之為一種算法,不如說是上面三種算法的一種組合。即,Java堆一般分為新生代和老年代,根據(jù)各個(gè)年代的特點(diǎn),分別采用上面三種算法的某一種來進(jìn)行垃圾回收
比如,在新生代中,每次垃圾回收都發(fā)現(xiàn)有大量的對(duì)象死去,只有少量存活,這種情況,采用復(fù)制算法效果會(huì)更好一點(diǎn),只需要復(fù)制少量存活的對(duì)象就可以完成收集。
而老年代中,因?yàn)閷?duì)象存活率高、沒有額外空間對(duì)它進(jìn)行分配擔(dān)保,就必須使用“標(biāo)記——清除”或“標(biāo)記——整理”算法來進(jìn)行回收。
堆內(nèi)存布局如下圖所示:
