這篇文章主要介紹Java中回收對象標(biāo)記和對象二次標(biāo)記的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)集安免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了1000多家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。一、對象的標(biāo)記
1、什么是標(biāo)記?怎么標(biāo)記?
第一個(gè)問題相信大家都知道,標(biāo)記就是對一些已死的對象打上記號(hào),方便垃圾收集器的清理。 至于怎么標(biāo)記,一般有兩種方法:引用計(jì)數(shù)和可達(dá)性分析。
引用計(jì)數(shù)實(shí)現(xiàn)起來比較簡單,就是給對象添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí)就加1,引用失效時(shí)就減1,當(dāng)計(jì)數(shù)器為0的時(shí)候就標(biāo)記為可回收。這種判斷效率很高,但是很多主流的虛擬機(jī)并沒有采用這種方法,主要是因?yàn)樗茈y解決幾個(gè)對象之間循環(huán)引用的問題,雖然不怎么用了,但還是值得我們學(xué)習(xí)!
public class Test { private Object obj; Public static void main(){ Test t1=new Test(); Test t2=new Test(); t1.obj=t2; t2.obj=t1; t1=null; t2=null; //如果對象在這行發(fā)生gc,那么t1和t2對象是否能被回收 System.gc(); } }
可達(dá)性分析的基本思路就是:通過將一些稱為"GC Roots"的對象作為起始點(diǎn),從這些節(jié)點(diǎn)開始搜索,搜索和該節(jié)點(diǎn)發(fā)生直接或者間接引用關(guān)系的對象,將這些對象以鏈的形式組合起來,形成一張“關(guān)系網(wǎng)”,又叫做引用鏈。最后垃圾收集器就回收一些不在這張關(guān)系網(wǎng)上的對象。如圖:
連接GC Roots對象的object是確定還存活的對象,而右邊的die obj由于和GCROOTS沒有關(guān)系,所以會(huì)標(biāo)記為可回收的對象。目前主流的商用虛擬機(jī)用的都是類似的方法。那什么對象才能作為“GC Roots”呢?在java中,有四種對象可以作為“GC Roots”
1:棧幀(第一章的名詞)中的引用對象。(棧中的)
2:靜態(tài)屬性引用的對象。(方法區(qū)中的)
3:常量引用的對象。(方法區(qū)中的)
4:本地方法棧中JNI引用的對象。(本地方法棧中的)
二、對象的二次回收
說過對象的標(biāo)記,但是不是被標(biāo)記了就肯定會(huì)被回收呢?不知道小伙伴們記不記得Object類有一個(gè)finalize()方法,所有類都繼承了Object類,因此也默認(rèn)實(shí)現(xiàn)了這個(gè)方法。
finalize的工作原理應(yīng)該是這樣的:一旦垃圾收集器準(zhǔn)備好釋放對象占用的存儲(chǔ)空間,它首先調(diào)用finalize(),而且只有在下一次垃圾收集過程中,才會(huì)真正回收對象的內(nèi)存.所以如果使用finalize(),就可以在垃圾收集期間進(jìn)行一些重要的清除或清掃工作.
finalize()在什么時(shí)候被調(diào)用?
有三種情況
1.所有對象被Garbage Collection時(shí)自動(dòng)調(diào)用,比如運(yùn)行System.gc()的時(shí)候.
2.程序退出時(shí)為每個(gè)對象調(diào)用一次finalize方法。
3.顯式的調(diào)用finalize方法
這個(gè)方法的用途就是:在該對象被回收之前,該對象的finalize()方法會(huì)被調(diào)用。這里的回收之前指的就是被標(biāo)記之后,問題就出在這里,有沒有一種情況就是原本一個(gè)對象開始不再上一章所講的“關(guān)系網(wǎng)”(引用鏈)中,但是當(dāng)開發(fā)者重寫了finalize()后,并且將該對象重新加入到了“關(guān)系網(wǎng)”中,也就是說該對象對我們還有用,不應(yīng)該被回收,但是已經(jīng)被標(biāo)記啦,怎么辦呢?
針對這個(gè)問題,虛擬機(jī)的做法是進(jìn)行兩次標(biāo)記,即第一次標(biāo)記不在“關(guān)系網(wǎng)”中的對象。第二次的話就要先判斷該對象有沒有實(shí)現(xiàn)finalize()方法了,如果沒有實(shí)現(xiàn)就直接判斷該對象可回收;如果實(shí)現(xiàn)了就會(huì)先放在一個(gè)隊(duì)列中,并由虛擬機(jī)建立的一個(gè)低優(yōu)先級(jí)的線程去執(zhí)行它,隨后就會(huì)進(jìn)行第二次的小規(guī)模標(biāo)記,在這次被標(biāo)記的對象就會(huì)真正的被回收了。
總結(jié):簡單說,對象先進(jìn)行第一次標(biāo)記,在下一次GC之前會(huì)執(zhí)行對象的finalize()方法。在執(zhí)行finalize()方法的時(shí)候判斷對象是否實(shí)現(xiàn)了finalize()方法,沒有實(shí)現(xiàn)直接清除;實(shí)現(xiàn)了,將對象放在一個(gè)隊(duì)列中執(zhí)行finalize方法,進(jìn)行第二次標(biāo)記
在java根搜索算法中判斷對象的可達(dá)性,對于不可達(dá)的對象,也并不一定是必須清理。這個(gè)時(shí)候有一個(gè)緩刑期,真正的判斷一個(gè)對象死亡,至少要經(jīng)過倆次標(biāo)記過程:如果對象在進(jìn)行根搜索后發(fā)現(xiàn)沒有與GC roots相關(guān)聯(lián)的引用鏈,那他將會(huì)第一次標(biāo)記并且進(jìn)行一次篩選,篩選的條件是此對象是否有必要執(zhí)行finalize()方法,當(dāng)對象沒有覆蓋finalize()方法,或者finalize()方法已經(jīng)被虛擬機(jī)調(diào)用過,虛擬機(jī)將這倆種情況都視為“沒有必要執(zhí)行”。
即當(dāng)一個(gè)對象重寫了finalize()方法的時(shí)候,這個(gè)對象被判定為有必要執(zhí)行finalize()方法,那么這個(gè)對象被放置在F-Queue隊(duì)列之中,并在稍后由一條由虛擬機(jī)自動(dòng)建立的、低優(yōu)先級(jí)的Finalizer線程去執(zhí)行。這里所謂的執(zhí)行是指虛擬機(jī)會(huì)出發(fā)這個(gè)方法,但不承諾會(huì)等待它運(yùn)行結(jié)束。這樣做的原因:如果一個(gè)對象在finalize()方法中執(zhí)行緩慢,或者發(fā)生了死循環(huán)(極端的情況下),將可能會(huì)導(dǎo)致F-Queue隊(duì)列中的其他對象永久處于等待狀態(tài),甚至導(dǎo)致整個(gè)內(nèi)存回收系統(tǒng)崩潰。finalize()方法是對象逃脫死亡命運(yùn)的最后一次機(jī)會(huì),稍后GC將對F-Queue中的對象進(jìn)行第二次小規(guī)模的標(biāo)記,如果對象要在finalize()中成功拯救自己----只要重新與引用鏈上的任何建立關(guān)聯(lián)即可,那么在第二次標(biāo)記時(shí)它將會(huì)被移出“即將回收”的集合;如果對象這時(shí)候沒有逃脫,就會(huì)被回收。代碼示例:參考《深入理解java虛擬機(jī)》對應(yīng)章節(jié)
以上是“Java中回收對象標(biāo)記和對象二次標(biāo)記的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
本文標(biāo)題:Java中回收對象標(biāo)記和對象二次標(biāo)記的示例分析-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://aaarwkj.com/article10/dihggo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、網(wǎng)站建設(shè)、面包屑導(dǎo)航、品牌網(wǎng)站設(shè)計(jì)、品牌網(wǎng)站制作、軟件開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容