本文主要介紹了JVM虛擬機(jī)中非常重要的兩個(gè)部分,GC 回收算法和垃圾收集器。從可回收對(duì)象的標(biāo)記開(kāi)始,詳細(xì)介紹 了四個(gè)主流的GC算法,詳細(xì)總結(jié)了各自的算法思路及優(yōu)缺點(diǎn), 提出了何種情況下應(yīng)該通常選用哪種算法。
目錄
1 標(biāo)記可回收對(duì)象
1.1?引用計(jì)數(shù)器
1.2?可達(dá)性分析算法
2 垃圾回收算法
2.1?清除算法
2.2?復(fù)制算法
2.3?標(biāo)記 - 整理算法
2.4?分代收集算法
3?結(jié)束語(yǔ)
1 標(biāo)記可回收對(duì)象
堆中幾乎放著所有的對(duì)象實(shí)例,對(duì)堆垃圾回收前的第一步就是要判斷哪些對(duì)象已經(jīng)死亡(即不能再被任何途徑使用的對(duì)象)。這個(gè)過(guò)程就是在后面垃圾收集器頻繁涉及的標(biāo)記過(guò)程。
1.1?引用計(jì)數(shù)器
這個(gè)方法簡(jiǎn)單易懂,就是給對(duì)象添加一個(gè)引用計(jì)數(shù)器,一 旦該對(duì)象被引用,計(jì)數(shù)器 +1,當(dāng)引用失效,計(jì)數(shù)器就 -1。此 時(shí)計(jì)數(shù)器為 0 的對(duì)象就是不可用對(duì)象?,F(xiàn)在幾乎已經(jīng)沒(méi)有JVM使用引用計(jì)數(shù)法來(lái)判斷對(duì)象是否可被回收了,因其無(wú)法解決對(duì)象之間互相循環(huán)引用的問(wèn)題。故現(xiàn)在一般使用下面的可達(dá)性分析算法。
1.2?可達(dá)性分析算法
可達(dá)性算法也叫根搜索法。這個(gè)算法的基本思想就是通過(guò) 一系列”GC Roots“對(duì)象作為起點(diǎn),從這些節(jié)點(diǎn)向下開(kāi)始搜索, 節(jié)點(diǎn)所走過(guò)的路徑稱(chēng)為引用鏈,當(dāng)一個(gè)對(duì)象到GCRoots沒(méi)有任何引用鏈相連的話,則證明此對(duì)象是不可用的。
這里要注意的是,即便在可達(dá)性算法中被判定為不可達(dá)對(duì)象,該對(duì)象也不是要絕對(duì)被清除的,還要經(jīng)歷再次被標(biāo)記才能真正被回收。此時(shí)就需要調(diào)用 finalize() 方法最終判定對(duì)象是否存活。
首先要對(duì)第一次標(biāo)記進(jìn)行一次篩選,以篩選出此對(duì)象是否有必要執(zhí)行finalize() 方法。當(dāng)這個(gè)對(duì)象沒(méi)有覆蓋finalize方法,或者finzlize方法已經(jīng)被虛擬機(jī)調(diào)用過(guò),則被視為“沒(méi)有必要執(zhí)行“,對(duì)象被回收。
如果被判定為“有必要執(zhí)行”,則對(duì)象將會(huì)被放置在 F-Queue 隊(duì)列之中,在第二次GC對(duì)F-Queue中的對(duì)象進(jìn)行標(biāo)記的過(guò)程中, 如果對(duì)象能夠抓住最后一次機(jī)會(huì),與引用鏈上的某一對(duì)象建立聯(lián)系,便可被移出,否則將被回收。
2 垃圾回收算法
垃圾回收算法,又叫GC算法,其中包含標(biāo)記 - 清除算法、 復(fù)制算法、標(biāo)記 - 整理算法和分代收集算法等。下面將詳細(xì)分析一下這四種常用算法。
2.1?清除算法
這是一個(gè)最基礎(chǔ)的收集算法,這個(gè)算法分為標(biāo)記”和”清 除“兩個(gè)階段。首先標(biāo)記出所有需要回收的對(duì)象,也就是用上面可達(dá)性分析算法進(jìn)行的標(biāo)記,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象。它有兩個(gè)不足的地方:效率問(wèn)題和空間問(wèn)題。兩個(gè)過(guò)程的效率都不高而且標(biāo)記清除后會(huì)產(chǎn)生大量不連續(xù)的碎 片,碎片過(guò)多會(huì)導(dǎo)致以后程序運(yùn)行時(shí)需要分配較大對(duì)象時(shí),無(wú)法找到足夠的連續(xù)內(nèi)存,而不得已再次觸發(fā)GC,會(huì)造成GC頻繁,故常用復(fù)制算法和標(biāo)記 - 整理算法作為改進(jìn)算法。
2.2?復(fù)制算法
復(fù)制算法的思路是把內(nèi)存分為大小相同的兩塊,每次只使用其中的一塊。當(dāng)這一塊的內(nèi)存使用完后,就將還存活的對(duì)象復(fù)制到另一塊區(qū),并且整齊排列好,然后再把使用的空間一次清理掉。這樣就使每次的內(nèi)存回收都是對(duì)內(nèi)存區(qū)間的一半進(jìn)行回收,也不用考慮內(nèi)存碎片問(wèn)題,簡(jiǎn)單高效。
這個(gè)算法就和新生代的 from 區(qū)和 to 區(qū)的過(guò)程很像,所以這個(gè)算法比較適合新生代。賦值的時(shí)候因?yàn)槎际呛苄〉膶?duì)象空間,所以效率還是比較高的,但是缺點(diǎn)很明顯,只有一半的內(nèi)存被利用起來(lái),浪費(fèi)了內(nèi)存空間。所以這個(gè)算法不適合老年代, 因?yàn)槔夏甏鷷?huì)存儲(chǔ)大對(duì)象,如果用這個(gè)算法就會(huì)導(dǎo)致內(nèi)存不足次數(shù)變頻繁,會(huì)使 Major GC 變頻繁,導(dǎo)致效率降低。
2.3?標(biāo)記 - 整理算法
標(biāo)記 - 整理算法也叫標(biāo)記 - 壓縮算法,標(biāo)記過(guò)程和“標(biāo)記 - 清除”算法一樣,基本思路是讓所有存活的對(duì)象向一端移動(dòng),然后直接清理掉邊界以外的內(nèi)存。這樣做直接避免了標(biāo)記 - 清除算法的碎片問(wèn)題和復(fù)制算法所涉及的空間問(wèn)題。這也是操作系統(tǒng)中常用的緊湊操作,緊湊操作之后再執(zhí)行動(dòng)態(tài)重定位分區(qū)分配算法,更新內(nèi)存中存活對(duì)象的新地址。
2.4?分代收集算法
現(xiàn)在的商用虛擬機(jī)的垃圾收集器基本都采用 " 分代收集 " 算法,這種算法就是根據(jù)對(duì)象存活周期的不同將內(nèi)存分為幾塊。 一般將java堆分為新生代和老年代,這樣我們就可以根據(jù)各個(gè)年代的特點(diǎn)選擇合適的垃圾收集算法。其實(shí)就是上面幾個(gè)算法的匯總。
3?結(jié)束語(yǔ)
本文主要介紹了怎樣判定一個(gè)算法是否被回收,以及四種常用的垃圾回收算法各自的思路及優(yōu)缺點(diǎn)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-620267.html
一般年輕代中執(zhí)行 GC 后,會(huì)有少量的對(duì)象存活,就會(huì)選用復(fù)制算法,只要付出少量的存活對(duì)象復(fù)制成本就可以完成收集。而老年代中因?yàn)閷?duì)象存活率高,沒(méi)有額外過(guò)多內(nèi)存空間對(duì) 它進(jìn)行分配擔(dān)保,就需要使用標(biāo)記 - 清理或者標(biāo)記 - 整理算法來(lái)進(jìn)行回收。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-620267.html
到了這里,關(guān)于小研究 - 淺析 JVM 中 GC 回收算法與垃圾收集器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!