java虛擬機(jī)學(xué)習(xí)筆記4-----對(duì)象的回收

? ? 先來(lái)回顧下運(yùn)行時(shí)數(shù)據(jù)區(qū),分為方法區(qū)、堆區(qū)、虛擬機(jī)棧、本地方法棧、程序計(jì)數(shù)器,其中虛擬機(jī)棧、本地方法棧、程序計(jì)數(shù)器是線(xiàn)程私有的,隨著線(xiàn)程的創(chuàng)建而生,線(xiàn)程的銷(xiāo)毀而滅,棧中的棧幀隨著方法的進(jìn)入和退出有條不紊執(zhí)行著入棧和出棧的操作,每一個(gè)棧幀中分配的內(nèi)存在類(lèi)結(jié)構(gòu)確定后就已知,因此這幾個(gè)區(qū)域的內(nèi)存分配和回收都是確定的,在方法結(jié)束或線(xiàn)程結(jié)束后就被銷(xiāo)毀了。而堆和方法區(qū)則不一樣,我們只有在程序運(yùn)行期間才能知道哪些對(duì)象會(huì)被創(chuàng)建,這部分內(nèi)存的分配和回收都是動(dòng)態(tài)的,垃圾回收器主要關(guān)注的是這部分內(nèi)存。

對(duì)象死了嗎?

? ? 垃圾回收器回收的死的對(duì)象,那么怎么確定一個(gè)對(duì)象已死呢?

引用計(jì)數(shù)器法

? ? 給對(duì)象添加一個(gè)引用計(jì)數(shù)器,每有一個(gè)地方引用該對(duì)象時(shí)就給引用計(jì)數(shù)器加1,當(dāng)引用計(jì)數(shù)器為0時(shí)該對(duì)象不能再被使用,則可以被垃圾回收器回收,但她很難解決一個(gè)問(wèn)題:對(duì)象之間的相互引用問(wèn)題:

public class test{

public Object o = null;

public static void main(String args[]){

Test t1 = new Test(); ? ?? Test t2 = new Test();

t1.o = t2; ? ?t2.o=t1;

t1=null; ?t2=null;

????}

test1 和test2都已經(jīng)不能被訪(fǎng)問(wèn)了,但他們內(nèi)部相互持有對(duì)象的引用,引用計(jì)數(shù)器為1,引用計(jì)數(shù)器無(wú)法通知垃圾回收器回收這兩個(gè)不再使用的對(duì)象。

}


可達(dá)性分析

? ? 這個(gè)算法的基本思路是通過(guò)一些列的稱(chēng)為"GC Roots" 的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)開(kāi)始向下搜索,搜索所走過(guò)的路徑稱(chēng)為引用鏈,當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連時(shí)(從GC Roots到這個(gè)對(duì)象不可達(dá)),則證明此對(duì)象不可用??梢员慌卸槭强苫厥諏?duì)象。


可達(dá)性分析算法

上面的這張圖,對(duì)象objectE、objectF、objectG雖然互相有關(guān)聯(lián),但是它們到GC Roots是不可達(dá)的,所以它們將會(huì)被判定為是可回收的對(duì)象

在java語(yǔ)言中,可作為GC Roots的對(duì)象有以下幾種:

1.虛擬機(jī)棧(棧幀的局部變量表里)中引用的對(duì)象

2.方法區(qū)中類(lèi)靜態(tài)屬性引用的對(duì)象

3.方法區(qū)中常量引用的對(duì)象

4.本地方法棧中(Native方法)引用的對(duì)象

引用

? ? 在JDK1.2以后加強(qiáng)了引用的概念,將引用分為強(qiáng)引用、弱引用、軟引用、虛引用,依次減弱。

? ? 強(qiáng)引用:就是代碼里Object a = new Object();這樣的引用,這類(lèi)的引用,只要強(qiáng)引用就不會(huì)被回收。

? ? 軟引用:是用來(lái)描述還有用但并非必須的對(duì)象,對(duì)于軟引用關(guān)聯(lián)的對(duì)象,在系統(tǒng)將要發(fā)生內(nèi)存溢出之前,回收這類(lèi)的對(duì)象,如果還不足則拋OutofMemoryError異常,提供SoftReference類(lèi)來(lái)實(shí)現(xiàn)軟引用。

? ? 弱引用:用來(lái)描述非必須的對(duì)象,被弱引用關(guān)聯(lián)的對(duì)象只能存活到下一次垃圾回收之前,當(dāng)垃圾回收器工作時(shí),無(wú)論當(dāng)前內(nèi)存是否充足,都會(huì)回收該類(lèi)對(duì)象,提供WeakReference類(lèi)來(lái)實(shí)現(xiàn)弱引用。

? ? 虛引用:是最弱的引用,也稱(chēng)為幽靈引用或幻影引用,一個(gè)對(duì)象是否有虛引用的存在,完全不會(huì)對(duì)其生存時(shí)間構(gòu)成影響,也無(wú)法通過(guò)一個(gè)虛引用來(lái)取得對(duì)象的實(shí)例,為對(duì)象虛引用關(guān)聯(lián)的唯一目的就是能在這個(gè)對(duì)象被垃圾器回收前得到一個(gè)通知,提供PhantomReference類(lèi)來(lái)實(shí)現(xiàn)虛引用。

對(duì)象是否回收:

? ? 在對(duì)象經(jīng)過(guò)可達(dá)性分析被判斷為不可達(dá)后,也不是一定被回收,要真正宣告一個(gè)對(duì)象死亡有兩次標(biāo)記過(guò)程在可達(dá)性分析后標(biāo)記為不可達(dá),那么它將會(huì)被進(jìn)行第一次標(biāo)記并進(jìn)行一次篩選,篩選的條件是該對(duì)象是否有必要執(zhí)行finalize(),如果沒(méi)有覆蓋Object的finalize()或已經(jīng)執(zhí)行過(guò)finalize(),則進(jìn)行第二次標(biāo)記并回收。如果對(duì)象有必須要執(zhí)行finalize(),那么這個(gè)對(duì)象將會(huì)加入到F-Queue隊(duì)列中,執(zhí)行她們的finalize(),但不一定會(huì)等到他們執(zhí)行結(jié)束,這是因?yàn)槿绻硞€(gè)對(duì)象的finalize()阻塞了,則可能導(dǎo)致垃圾回收器工作異常,從而系統(tǒng)崩潰,如果在finalize()中將對(duì)象自身的引用賦給某個(gè)對(duì)象的屬性,則可以擺脫這一次的回收,如果沒(méi)有賦值則進(jìn)行第二次標(biāo)記。

注:finalize()只會(huì)被系統(tǒng)調(diào)用一次。最好不要使用她。

回收方法區(qū)

????????很多人認(rèn)為方法區(qū)(或者Hotspot虛擬機(jī)中的永久帶)是不會(huì)被回收的,因?yàn)榛厥辗椒▍^(qū)的性?xún)r(jià)比或者說(shuō)效率比較低,在堆中尤其是新生代,常規(guī)應(yīng)用進(jìn)行一次垃圾收集一般可以達(dá)到70%-95%的空間,而永久帶的垃圾收集效率遠(yuǎn)低于此。

? ? ? ? 永久帶的垃圾收集主要包含兩部分:廢棄常量和無(wú)用的類(lèi)(類(lèi)卸載)。

? ? ? ? 回收廢棄常量與回收java堆中的對(duì)象非常類(lèi)似,以常量池中字面量的回收為例,加入一個(gè)字符串"abc"已經(jīng)進(jìn)入到常量池,但當(dāng)前系統(tǒng)中沒(méi)有任何一個(gè)String對(duì)象是叫做"abc"的,就是沒(méi)有任何引用去指向這個(gè)對(duì)象,如果這時(shí)發(fā)生內(nèi)存回收,而且有必要的話(huà),這個(gè)"abc"常量將被系統(tǒng)回收,常量池中其他類(lèi)(接口)、方法、字段的符號(hào)引用也與此類(lèi)似。

? ? ? ? 無(wú)用類(lèi)回收則對(duì)象苛刻許多,類(lèi)需要同時(shí)滿(mǎn)足下面三個(gè)條件才算是"無(wú)用的類(lèi)":

1.該類(lèi)所有的實(shí)例都已經(jīng)被回收(堆中沒(méi)有該類(lèi)的實(shí)例)

2.加載該類(lèi)的ClassLoader已經(jīng)被回收

3.該類(lèi)對(duì)應(yīng)的Class對(duì)象沒(méi)有在任何地方被引用,無(wú)法在任何地方通過(guò)反射訪(fǎng)問(wèn)該類(lèi)的方法。

????????虛擬機(jī)可以對(duì)滿(mǎn)足上述三個(gè)條件的類(lèi)進(jìn)行回收,并不是一定會(huì)被回收,是否對(duì)類(lèi)進(jìn)行回收需要設(shè)置虛擬機(jī)的參數(shù)(真想弄去查參數(shù)吧)。需要回收的場(chǎng)景:在大量使用反射、動(dòng)態(tài)代理、CGlib等ByteCode框架、動(dòng)態(tài)生成JSP以及OSGI這類(lèi)頻繁自定義ClassLoader的場(chǎng)景都需要虛擬機(jī)具備類(lèi)卸載的功能,以保證永久代不會(huì)溢出。


下一節(jié)將介紹垃圾回收算法。


當(dāng)它本可進(jìn)取時(shí),卻故作謙卑;

當(dāng)它在空虛時(shí),用愛(ài)欲來(lái)填充;

在困難和容易之間,它選擇了容易;

它犯了錯(cuò),卻借由別人也會(huì)犯錯(cuò)來(lái)寬慰自己;

它自由軟弱,卻把它認(rèn)為是生命的堅(jiān)韌;

當(dāng)它鄙夷一張丑惡的嘴臉時(shí),卻不知那正是自己面具中的一副;

它側(cè)身于生活的污泥中,雖不甘心,卻又畏首畏尾。

?著作權(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)容