常見(jiàn)的GC回收算法及其含義

在探討Java垃圾回收機(jī)制之前,我們首先應(yīng)該記住一個(gè)單詞:Stop-the-World。Stop-the-world意味著 JVM由于要執(zhí)行GC而停止了應(yīng)用程序的執(zhí)行,并且這種情形會(huì)在任何一種GC算法中發(fā)生。當(dāng)Stop-the-world發(fā)生時(shí),除了GC所需的線程以外,所有線程都處于等待狀態(tài)直到GC任務(wù)完成。事實(shí)上,GC優(yōu)化很多時(shí)候就是指減少Stop-the-world發(fā)生的時(shí)間,從而使系統(tǒng)具有 高吞吐 、低停頓 的特點(diǎn)。

1、標(biāo)記清除算法

標(biāo)記-清除算法分為標(biāo)記和清除兩個(gè)階段。該算法首先從根集合進(jìn)行掃描,對(duì)存活的對(duì)象對(duì)象標(biāo)記,標(biāo)記完畢后,再掃描整個(gè)空間中未被標(biāo)記的對(duì)象并進(jìn)行回收,如下圖所示。


標(biāo)記-清除算法的主要不足有兩個(gè):

效率問(wèn)題:標(biāo)記和清除兩個(gè)過(guò)程的效率都不高;

空間問(wèn)題:標(biāo)記-清除算法不需要進(jìn)行對(duì)象的移動(dòng),并且僅對(duì)不存活的對(duì)象進(jìn)行處理,因此標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會(huì)導(dǎo)致以后在程序運(yùn)行過(guò)程中需要分配較大對(duì)象時(shí),無(wú)法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作。


2、復(fù)制算法

  復(fù)制算法將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊的內(nèi)存用完了,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已使用過(guò)的內(nèi)存空間一次清理掉。這種算法適用于對(duì)象存活率低的場(chǎng)景,比如新生代。這樣使得每次都是對(duì)整個(gè)半?yún)^(qū)進(jìn)行內(nèi)存回收,內(nèi)存分配時(shí)也就不用考慮內(nèi)存碎片等復(fù)雜情況,只要移動(dòng)堆頂指針,按順序分配內(nèi)存即可,實(shí)現(xiàn)簡(jiǎn)單,運(yùn)行高效。該算法示意圖如下所示:


事實(shí)上,現(xiàn)在商用的虛擬機(jī)都采用這種算法來(lái)回收新生代。因?yàn)檠芯堪l(fā)現(xiàn),新生代中的對(duì)象每次回收都基本上只有10%左右的對(duì)象存活,所以需要復(fù)制的對(duì)象很少,效率還不錯(cuò)。實(shí)踐中會(huì)將新生代內(nèi)存分為一塊較大的Eden空間和兩塊較小的Survivor空間 (如下圖所示),每次使用Eden和其中一塊Survivor。當(dāng)回收時(shí),將Eden和Survivor中還存活著的對(duì)象一次地復(fù)制到另外一塊Survivor空間上,最后清理掉Eden和剛才用過(guò)的Survivor空間。HotSpot虛擬機(jī)默認(rèn)Eden和Survivor的大小比例是 8:1,也就是每次新生代中可用內(nèi)存空間為整個(gè)新生代容量的90% ( 80%+10% ),只有10% 的內(nèi)存會(huì)被“浪費(fèi)”。


3、標(biāo)記整理算法

  復(fù)制收集算法在對(duì)象存活率較高時(shí)就要進(jìn)行較多的復(fù)制操作,效率將會(huì)變低。更關(guān)鍵的是,如果不想浪費(fèi)50%的空間,就需要有額外的空間進(jìn)行分配擔(dān)保,以應(yīng)對(duì)被使用的內(nèi)存中所有對(duì)象都100%存活的極端情況,所以在老年代一般不能直接選用這種算法。標(biāo)記整理算法的標(biāo)記過(guò)程類似標(biāo)記清除算法,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活的對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存,類似于磁盤整理的過(guò)程,該垃圾回收算法適用于對(duì)象存活率高的場(chǎng)景(老年代),其作用原理如下圖所示。


標(biāo)記整理算法與標(biāo)記清除算法最顯著的區(qū)別是:標(biāo)記清除算法不進(jìn)行對(duì)象的移動(dòng),并且僅對(duì)不存活的對(duì)象進(jìn)行處理;而標(biāo)記整理算法會(huì)將所有的存活對(duì)象移動(dòng)到一端,并對(duì)不存活對(duì)象進(jìn)行處理,因此其不會(huì)產(chǎn)生內(nèi)存碎片。標(biāo)記整理算法的作用示意圖如下:


4、分代收集算法

  對(duì)于一個(gè)大型的系統(tǒng),當(dāng)創(chuàng)建的對(duì)象和方法變量比較多時(shí),堆內(nèi)存中的對(duì)象也會(huì)比較多,如果逐一分析對(duì)象是否該回收,那么勢(shì)必造成效率低下。分代收集算法是基于這樣一個(gè)事實(shí):不同的對(duì)象的生命周期(存活情況)是不一樣的,而不同生命周期的對(duì)象位于堆中不同的區(qū)域,因此對(duì)堆內(nèi)存不同區(qū)域采用不同的策略進(jìn)行回收可以提高 JVM 的執(zhí)行效率。當(dāng)代商用虛擬機(jī)使用的都是分代收集算法:新生代對(duì)象存活率低,就采用復(fù)制算法;老年代存活率高,就用標(biāo)記清除算法或者標(biāo)記整理算法。Java堆內(nèi)存一般可以分為新生代、老年代和永久代三個(gè)模塊,如下圖所示:


1).新生代(Young Generation)

  新生代的目標(biāo)就是盡可能快速的收集掉那些生命周期短的對(duì)象,一般情況下,所有新生成的對(duì)象首先都是放在新生代的。新生代內(nèi)存按照8:1:1的比例分為一個(gè)eden區(qū)和兩個(gè)survivor(survivor0,survivor1)區(qū),大部分對(duì)象在Eden區(qū)中生成。在進(jìn)行垃圾回收時(shí),先將eden區(qū)存活對(duì)象復(fù)制到survivor0區(qū),然后清空eden區(qū),當(dāng)這個(gè)survivor0區(qū)也滿了時(shí),則將eden區(qū)和survivor0區(qū)存活對(duì)象復(fù)制到survivor1區(qū),然后清空eden和這個(gè)survivor0區(qū),此時(shí)survivor0區(qū)是空的,然后交換survivor0區(qū)和survivor1區(qū)的角色(即下次垃圾回收時(shí)會(huì)掃描Eden區(qū)和survivor1區(qū)),即保持survivor0區(qū)為空,如此往復(fù)。特別地,當(dāng)survivor1區(qū)也不足以存放eden區(qū)和survivor0區(qū)的存活對(duì)象時(shí),就將存活對(duì)象直接存放到老年代。如果老年代也滿了,就會(huì)觸發(fā)一次FullGC,也就是新生代、老年代都進(jìn)行回收。注意,新生代發(fā)生的GC也叫做MinorGC,MinorGC發(fā)生頻率比較高,不一定等 Eden區(qū)滿了才觸發(fā)。

2).老年代(Old Generation)

  老年代存放的都是一些生命周期較長(zhǎng)的對(duì)象,就像上面所敘述的那樣,在新生代中經(jīng)歷了N次垃圾回收后仍然存活的對(duì)象就會(huì)被放到老年代中。此外,老年代的內(nèi)存也比新生代大很多(大概比例是1:2),當(dāng)老年代滿時(shí)會(huì)觸發(fā)Major GC(Full GC),老年代對(duì)象存活時(shí)間比較長(zhǎng),因此FullGC發(fā)生的頻率比較低。

3).永久代(Permanent Generation)

  永久代主要用于存放靜態(tài)文件,如Java類、方法等。永久代對(duì)垃圾回收沒(méi)有顯著影響,但是有些應(yīng)用可能動(dòng)態(tài)生成或者調(diào)用一些class,例如使用反射、動(dòng)態(tài)代理、CGLib等bytecode框架時(shí),在這種時(shí)候需要設(shè)置一個(gè)比較大的永久代空間來(lái)存放這些運(yùn)行過(guò)程中新增的類。

5、小結(jié)


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容