聲明:本文摘抄自《深入理解Java虛擬機(jī)》一書,本文完全為自我學(xué)習(xí),請感興趣的同學(xué)購買正版,支持原創(chuàng)
- 標(biāo)記-清除算法
- 復(fù)制算法
- 標(biāo)記-整理算法
標(biāo)記-清除算法(Mark-Sweep)
標(biāo)記-清除算法分為“標(biāo)記”和“清除”兩個階段:首先標(biāo)記出所有需要回收的對象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對象。
標(biāo)記-清除算法的不足有兩個:一個是效率問題,標(biāo)記和清除兩個過程效率都不高;另一個是空間問題,標(biāo)記清除后會產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會導(dǎo)致以后程序在分配較大內(nèi)存時,無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動作。

復(fù)制算法(Copying)
復(fù)制算法是將內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中一塊,當(dāng)這一塊內(nèi)存用完了,就將還存活的對象復(fù)制到另一塊上面,然后在把已使用過的內(nèi)存空間一次性清理掉。這樣使的每次都是對整個半?yún)^(qū)進(jìn)行內(nèi)存回收,內(nèi)存分配時也不用考慮內(nèi)存碎片等復(fù)雜情況。這種算法的代價是將內(nèi)存縮小為原來的一半,未免太高了一點。

現(xiàn)在的商業(yè)虛擬機(jī)都采用這種算法來回收新生代,IBM公司的專門研究表面,新生代中的對象98%是“朝生夕死”的,所以并不需要按照1:1的比例來劃分內(nèi)存空間,而是將內(nèi)存分為一塊較大的Eden空間和兩塊較小的Survivor空間。HotSpot虛擬機(jī)默認(rèn)Eden和Survivor的大小比例是8:1:1,這樣只有10%的內(nèi)存會被“浪費(fèi)”。
為什么不是一塊Survivor空間而是兩塊?
這里涉及到一個新生代和老年代的存活周期的問題,比如一個對象在新生代經(jīng)歷15次(僅供參考)GC,就可以移到老年代了。問題來了,當(dāng)我們第一次GC的時候,我們可以把Eden區(qū)的存活對象放到Survivor A空間,但是第二次GC的時候,Survivor A空間的存活對象也需要再次用Copying算法,放到Survivor B空間上,而把剛剛的Survivor A空間和Eden空間清除。第三次GC時,又把Survivor B空間的存活對象復(fù)制到Survivor A空間,如此反復(fù)。所以,這里就需要兩塊Survivor空間來回倒騰。
標(biāo)記-整理算法(Mark-Compact)
標(biāo)記-整理算法是將所有存活的對象都向一端移動,然后直接清理掉端邊界以外的內(nèi)存。適合于老年代。
