Java詳解對(duì)象終止方法finalize()的用法
finalize()方法機(jī)制
Java 語(yǔ)言提供了對(duì)象終止(finalization)機(jī)制來允許開發(fā)人員提供對(duì)象被銷毀之前的自定義處理邏輯。
當(dāng)GC去回收垃圾時(shí), 總會(huì)在即將回收之前調(diào)用這個(gè)對(duì)象的 finalize()方法 , 一個(gè)對(duì)象finalize()方法只會(huì)被調(diào)用一次
finalize()方法可以被重寫,通常在這個(gè)方法中進(jìn)行一些資源釋放和清理的工作,比如關(guān)閉文件、套接字和數(shù)據(jù)庫(kù)連接等。
我們一般最好不要主動(dòng)去調(diào)用對(duì)象的finalize()方法, 理由有以下三點(diǎn) :
1.在 finalize()時(shí)可能會(huì)導(dǎo)致對(duì)象復(fù)活。
2.finalize()方法的執(zhí)行時(shí)間是沒有保障的,它完全由 GC 線程決定,極端情況下,若不發(fā)生 GC,則 finalize()方法將沒有執(zhí)行機(jī)會(huì)。
3.一個(gè)糟糕的 finalize()會(huì)嚴(yán)重影響 GC 的性能。比如 finalize 是個(gè)死循環(huán)。
為什么會(huì)有這種機(jī)制呢 ?
我們先來了解 jvm 為對(duì)象定義的三種狀態(tài)
第一次被 jvm 標(biāo)為垃圾的對(duì)象此時(shí)處于"緩刑"階段, 也就是說它此時(shí)并不是非死不可的
可觸及的:從根節(jié)點(diǎn)開始,可以到達(dá)這個(gè)對(duì)象。
可復(fù)活的:對(duì)象的所有引用都被釋放,但是對(duì)象有可能在 finalize()中復(fù)活。
不可觸及的:對(duì)象的 finalize()被調(diào)用,并且沒有復(fù)活,那么就會(huì)進(jìn)入不可觸及狀態(tài)。不可觸及的對(duì)象不可能被復(fù)活,因?yàn)?finalize()只會(huì)被調(diào)用一次。
以上 3 種狀態(tài)中,是由于 finalize()方法的存在,進(jìn)行的區(qū)分。只有在對(duì)象不可觸及時(shí)才可以被回收
可觸及的, 意思就是說, 對(duì)象此時(shí)存在引用鏈, 是存活的, 可復(fù)活的意思是說, 此對(duì)象雖然已經(jīng)被GC標(biāo)為了垃圾, 但是此時(shí)未調(diào)用 finalize() 方法, 這個(gè)對(duì)象是有可能在finalize()中復(fù)活的. 不可觸及的就是說, 此時(shí)finalize()方法已經(jīng)被調(diào)用過了(沒有復(fù)活), 這個(gè)對(duì)象最終的命運(yùn)已經(jīng)是非死不可了, 只能靜等GC去回收它
那么具體的過程是怎樣的呢?
判定一個(gè)對(duì)象 objA 是否可回收,至少要經(jīng)歷兩次標(biāo)記過程:
1.如果對(duì)象 objA 到 GC Roots 沒有引用鏈,則進(jìn)行第一次標(biāo)記。
2.進(jìn)行篩選,判斷此對(duì)象是否有必要執(zhí)行 finalize()方法
如果對(duì)象 objA 沒有重寫 finalize()方法,或者 finalize()方法已經(jīng)被虛擬機(jī)調(diào)用過,則虛擬機(jī)視為“沒有必要執(zhí)行”,objA 被判定為不可觸及的。
如果對(duì)象 objA 重寫了 finalize()方法,且還未執(zhí)行過,那么 objA 會(huì)被插入到 F-Queue 隊(duì)列中,由一個(gè)虛擬機(jī)自動(dòng)創(chuàng)建的、低優(yōu)先級(jí)的 Finalizer 線程觸發(fā)其 finalize()方法執(zhí)行。finalize()方法是對(duì)象逃脫死亡的最后機(jī)會(huì),稍后 GC 會(huì)對(duì) F-Queue 隊(duì)列中的對(duì)象進(jìn)行第二次標(biāo)記。如果 objA 在 finalize()方法中與引用鏈上的任何一個(gè)對(duì)象建立了聯(lián)系,那么在第二次標(biāo)記時(shí),objA 會(huì)被移出“即將回收”集合。之后,對(duì)象會(huì)再次出現(xiàn)沒有引用存在的情況. 在這個(gè)情況下,finalize()方法不會(huì)被再次調(diào)用,對(duì)象會(huì)直接變成不可觸及的狀態(tài),也就是說,一個(gè)對(duì)象的 finalize()方法只會(huì)被調(diào)用一次。
接著我們用代碼演示對(duì)象的復(fù)活
public class CanReliveObj { public static CanReliveObj obj;//類變量,屬于 GC Root //此方法只能被調(diào)用一次 @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("調(diào)用當(dāng)前類重寫的finalize()方法"); obj = this;//當(dāng)前待回收的對(duì)象在finalize()方法中與引用鏈上的一個(gè)對(duì)象obj建立了聯(lián)系 } public static void main(String[] args) { try { obj = new CanReliveObj(); // 對(duì)象第一次成功拯救自己 obj = null; System.gc();//調(diào)用垃圾回收器 System.out.println("第1次 gc"); // 因?yàn)镕inalizer線程優(yōu)先級(jí)很低,暫停2秒,以等待它 Thread.sleep(2000); if (obj == null) { System.out.println("obj is dead"); } else { System.out.println("obj is still alive"); } System.out.println("第2次 gc"); // 下面這段代碼與上面的完全相同,但是這次自救卻失敗了 obj = null; System.gc(); // 因?yàn)镕inalizer線程優(yōu)先級(jí)很低,暫停2秒,以等待它 Thread.sleep(2000); if (obj == null) { System.out.println("obj is dead"); } else { System.out.println("obj is still alive"); } } catch (InterruptedException e) { e.printStackTrace(); } } }
執(zhí)行結(jié)果 :
先將引用指向 null , 這時(shí)第一次GC , 我們重寫了finalize()方法, 致使對(duì)象在第一次垃圾回收時(shí)成功自救, 第二次再將引用指向null , 因?yàn)閒inalize() 方法只會(huì)被執(zhí)行一次, 這時(shí)對(duì)象只能等待死亡
到此這篇關(guān)于Java詳解對(duì)象終止方法finalize()的用法的文章就介紹到這了,更多相關(guān)Java finalize()內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Security 自定義資源服務(wù)器實(shí)踐過程
這篇文章主要介紹了Spring Security 自定義資源服務(wù)器實(shí)踐,我們通過自己搭建的授權(quán)服務(wù)器和資源服務(wù)器,完整體驗(yàn)了OAuth2流程,需要的朋友可以參考下2022-08-08詳解java實(shí)現(xiàn)簡(jiǎn)單掃碼登錄功能(模仿微信網(wǎng)頁(yè)版掃碼)
這篇文章主要介紹了java實(shí)現(xiàn)簡(jiǎn)單掃碼登錄功能(模仿微信網(wǎng)頁(yè)版掃碼),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05MAC算法之消息摘要算法HmacMD5的實(shí)現(xiàn)
這篇文章主要介紹了MAC算法之消息摘要算法HmacMD5的實(shí)現(xiàn)的相關(guān)資料,這里提供實(shí)例,幫助大家學(xué)習(xí)理解這部分知識(shí),需要的朋友可以參考下2017-08-08Java數(shù)組集合的深度復(fù)制代碼實(shí)例
這篇文章主要介紹了Java數(shù)組集合的深度復(fù)制代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11IntelliJ IDEA搜索整個(gè)項(xiàng)目進(jìn)行全局替換(有危險(xiǎn)慎用)
今天小編就為大家分享一篇關(guān)于IntelliJ IDEA搜索整個(gè)項(xiàng)目進(jìn)行全局替換(有危險(xiǎn)慎用),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-10-10SpringBoot 使用jwt進(jìn)行身份驗(yàn)證的方法示例
這篇文章主要介紹了SpringBoot 使用jwt進(jìn)行身份驗(yàn)證的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12