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