這里介紹幾種垃圾收集算法的思想及其發(fā)展過程翅睛。
標(biāo)記-清除算法(Mark-Sweep)
標(biāo)記-清除算法是最基礎(chǔ)的收集算法影所,后續(xù)的收集算法都是基于這種思路并對(duì)其缺點(diǎn)進(jìn)行改進(jìn)而得到的。
執(zhí)行過程
- 標(biāo)記出所有需要回收的對(duì)象踩衩。
- 統(tǒng)一回收掉所有被標(biāo)記的對(duì)象。
缺點(diǎn)
- 效率問題:標(biāo)記和清除過程的效率都不高。
- 空間問題:標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片蚓胸,空間碎片太多可能會(huì)導(dǎo)致,當(dāng)程序在以后的運(yùn)行過程中需要分配較大對(duì)象時(shí)無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作除师。
復(fù)制算法(Copying)
為了解決標(biāo)記-清除算法的缺點(diǎn)就出現(xiàn)了復(fù)制算法沛膳。
執(zhí)行過程
- 將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中一塊汛聚。
- 當(dāng)正在使用的這塊內(nèi)存用完了锹安,就將存活的對(duì)象復(fù)制到另外一塊上面。
- 然后把已使用過的內(nèi)存空間一次清理掉倚舀。
優(yōu)點(diǎn)
每次都是對(duì)其中一塊內(nèi)存進(jìn)行回收叹哭,內(nèi)存分配時(shí)不需要考慮內(nèi)存碎片等復(fù)雜情況,只要移動(dòng)堆頂指針痕貌,按順序分配內(nèi)存即可风罩,實(shí)現(xiàn)簡單,運(yùn)行高效舵稠。
缺點(diǎn)
這種算法的代價(jià)是將內(nèi)存縮小為原來的一半超升。
改進(jìn)后的復(fù)制算法
現(xiàn)代的商業(yè)虛擬機(jī)都是采用復(fù)制算法來回收新生代,而研究表明新生代中的對(duì)象98%是朝生夕死的哺徊,所以并不需要按照1:1的比例來劃分內(nèi)存空間室琢。
執(zhí)行過程
- 將內(nèi)存分為一塊較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中的一塊Survivor空間落追。
- 當(dāng)回收時(shí)盈滴,將Eden和Survivor空間中還存活的對(duì)象一次性拷貝到另外一塊沒有使用的Survivor空間上。
- 最后清理掉Eden和剛才用過的Survivor空間轿钠。
優(yōu)點(diǎn)
HotSpot虛擬機(jī)默認(rèn)Eden和Survivor的大小比例是8:1巢钓,也就是每次新生代中可用內(nèi)存空間為整個(gè)新生代容量的90%(80%+10%)病苗,只有10%的內(nèi)存是會(huì)被“浪費(fèi)”的。
缺點(diǎn)
- 98%的對(duì)象可回收只是一般場(chǎng)景下的數(shù)據(jù)竿报,沒有辦法保證每次回收都只有不多于10%的對(duì)象存活铅乡,當(dāng)Survivor空間不夠用時(shí),需要依賴其他內(nèi)存(這里指老年代)進(jìn)行分配擔(dān)保(Handle Promotion)烈菌。
- 同時(shí)在對(duì)象存活率較高的時(shí)候要執(zhí)行較多的復(fù)制操作阵幸,效率將會(huì)變低。
標(biāo)記-整理算法(Mark-Compact)
由于復(fù)制收集算法在對(duì)象存活率較高時(shí)需要分配擔(dān)保和較多的復(fù)制操作芽世,老年代一般不能直接選用這種算法挚赊。于是,根據(jù)老年代的特別济瓢,有人就提出了一種“標(biāo)記-整理”算法荠割。
執(zhí)行過程
- 標(biāo)記過程仍然與“標(biāo)記-清除”算法一樣。
- 將所有存活對(duì)象都移動(dòng)到內(nèi)存的一端旺矾。
- 直接清理掉端邊界以外的內(nèi)存蔑鹦。
分代收集算法(Generational Collection)
當(dāng)前商業(yè)虛擬機(jī)的垃圾收集都是采用分代收集算法。這種算法沒什么新的思想箕宙,只是根據(jù)對(duì)象的存活周期的不同將內(nèi)存分為幾塊嚎朽。一般是把Java堆分為新生代和老年代,這樣就可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ā?/p>
- 在新生代中柬帕,每次垃圾收集時(shí)都只有少量對(duì)象存活哟忍,所以選用復(fù)制算法,只需要付出少量存活對(duì)象的復(fù)制成本就可以完成收集陷寝。
- 在老年代中锅很,因?yàn)閷?duì)象存活率高,沒有額外空間對(duì)它進(jìn)行分配擔(dān)保凤跑,就必須使用“標(biāo)記-清除”或“標(biāo)記-整理”算法來進(jìn)行回收爆安。