更新時間:2021-10-22 來源:黑馬程序員 瀏覽量:
垃圾收集算法有標(biāo)記-清除算法、復(fù)制算法、標(biāo)記真理算法、分代收集算法四種,下面我們詳細(xì)介紹。
標(biāo)記-清除算法:
最基礎(chǔ)的收集算法是標(biāo)記-清除算法,如同它的名字一樣,分為標(biāo)記和清除兩個階段。第一步標(biāo)記出所要回收的對象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對象。如何標(biāo)記已經(jīng)在上面說過了,之所以說它是最基本的垃圾收集算法,原因在于其他的算法也是基于這種思路并對其不足做以改進(jìn)得到的。
主要問題有兩個:
第一個是效率問題,標(biāo)記和清除的效率都不高。
第二個是空間分配問題,標(biāo)記清除后會產(chǎn)生大量的不連續(xù)的內(nèi)存空間,空間碎片太多可能會導(dǎo)致以后程序在運(yùn)行過程中需要給較大對象分配空間時,無法找到足夠的內(nèi)存空間,而不得不提前進(jìn)行一次垃圾收集動作。如圖所示,會產(chǎn)生大量的垃圾碎片,導(dǎo)致空間的利用率不高。
復(fù)制算法
為了解決效率問題,一種稱為復(fù)制的收集算法出現(xiàn)了,它將可用內(nèi)存分為大小相等的兩塊,每次只使用其中的一塊,當(dāng)這一塊內(nèi)存區(qū)域用完了,就將還存活的對象復(fù)制到另一塊內(nèi)存中,然后再把已使用的空間一次性清理掉,這樣每次都是對半個區(qū)域進(jìn)行回收,內(nèi)存分配時也就不用考慮碎片等問題了,只要移動堆頂指針,按順序分配內(nèi)存即可,實現(xiàn)簡單,運(yùn)行高效。
只是這種做法將原來的內(nèi)存縮小為一半,代價太高了。
現(xiàn)在的商用虛擬機(jī)都采用這種方法來回收新生代,IBM專門研究表明,新生代中的對象98%都是"朝生夕死"的,所以并不需要按照1:1劃分內(nèi)存區(qū)域,而是將內(nèi)存分為一塊較大的區(qū)域給Eden和兩塊較小的區(qū)域給Survivor,
當(dāng)回收時,將Eden和Survivor區(qū)中還存活的對象一次性復(fù)制到另一塊Survivor區(qū),然后將Eden和Survivor區(qū)進(jìn)行一次性清理。Hotspot區(qū)默認(rèn)的Eden和Survivor的比例為8:1,也就是說新生代的可用內(nèi)存為90%,只有10%的內(nèi)存會被劃分為保留內(nèi)存。當(dāng)然,大多數(shù)情況下是98%,但我們不能保證每次回收的存活對象都小于10%,當(dāng)Survivor區(qū)不夠用時,需要依賴其他區(qū)域進(jìn)行分配擔(dān)保。如果另外一塊Survivor區(qū)已經(jīng)不夠用了,對象可通過內(nèi)存擔(dān)保機(jī)制直接進(jìn)入到老年代。
標(biāo)記整理算法
復(fù)制算法在存活對象比例比較高的情況下要進(jìn)行較多的復(fù)制操作,效率將會變低,更關(guān)鍵的是,如果不想浪費(fèi)50%的區(qū)域,則需要額外的空間進(jìn)行分配擔(dān)保,以應(yīng)對內(nèi)存中100%對象都存活的極端情況,所以老年代一般不選用這種算法。
根據(jù)老年代的特點,有人提出了另一種標(biāo)記-整理算法,標(biāo)記過程與標(biāo)記-清除算法一致,但后續(xù)步驟不是對可回收對象直接進(jìn)行清理,而是讓所有存活對象都向一端移動,然后直接清理掉邊界外的對象。示意圖如下:
分代收集算法
當(dāng)前商用的垃圾收集器都采用的是分代垃圾回收,這種算法沒有什么新的思想,只是根據(jù)對象的存活周期將內(nèi)存分為幾塊,一般是將java堆分為新生代和老年代,這樣就可以根據(jù)各個代的對象特點選用最適當(dāng)?shù)幕厥账惴?。在新生代,每次垃圾回收都有大量的對象死去,只有少量存活,這樣就適合采用復(fù)制算法。只需要付出少量的對象復(fù)制成本就可以完成垃圾回收,而老年代因為存活率高,沒有其他內(nèi)存進(jìn)行分配擔(dān)保,就必須使用標(biāo)記-清理或者標(biāo)記-整理進(jìn)行回收。
1. 分代分為年輕代和老年代,年輕代里頭又分為 Eden區(qū)和Survivor區(qū),通常默認(rèn)的比例為8:1:1, 每次只保留10%的空間用作預(yù)留區(qū)域,然后將90%的空間可以用作新生對象。
2. 每一次垃圾回收之后,存活的對象年齡對應(yīng)+1,當(dāng)經(jīng)歷15次還依然存活的對象,我們讓它直接進(jìn)入到老年代;
3. 另外一種進(jìn)入到老年代的方式是內(nèi)存擔(dān)保機(jī)制,也就是當(dāng)新生代的空間不夠的時候,對象直接進(jìn)入到老年代;
4. 新生代的垃圾回收叫Minor GC,老年代的叫Full GC。
添加QQ(注意~~添加好友界面,選擇找人):435946716,【免費(fèi)】獲取《JVM核心教程:JVM從門到精通_JVM虛擬機(jī)底層原理深入教程》全套視頻教程+配套資料。
猜你喜歡