Java中Object對象finalize方法詳細解析

簡書:capo 轉(zhuǎn)載請注明原創(chuàng)出處,謝謝编检!

前言:

今天我們來看看Object中一個經(jīng)常被人遺忘的方法,finalize方法耕皮。老規(guī)矩撑碴,我們先看看Javadoc是怎樣描述這個方法的

 /**
     * Called by the garbage collector on an object when garbage collection
     * determines that there are no more references to the object.
     * A subclass overrides the {@code finalize} method to dispose of
     * system resources or to perform other cleanup.
     * <p>
     * The general contract of {@code finalize} -is that it is invoked
     * if and when the Java? virtual
     * machine has determined that there is no longer any
     * means by which this object can be accessed by any thread that has
     * not yet died, except as a result of an action taken by the
     * finalization of some other object or class which is ready to be
     * finalized. The {@code finalize} method may take any action, including
     * making this object available again to other threads; the usual purpose
     * of {@code finalize}, however, is to perform cleanup actions before
     * the object is irrevocably discarded. For example, the finalize method
     * for an object that represents an input/output connection might perform
     * explicit I/O transactions to break the connection before the object is
     * permanently discarded.
     * <p>
     * The {@code finalize} method of class {@code Object} performs no
     * special action; it simply returns normally. Subclasses of
     * {@code Object} may override this definition.
     * <p>
     * The Java programming language does not guarantee which thread will
     * invoke the {@code finalize} method for any given object. It is
     * guaranteed, however, that the thread that invokes finalize will not
     * be holding any user-visible synchronization locks when finalize is
     * invoked. If an uncaught exception is thrown by the finalize method,
     * the exception is ignored and finalization of that object terminates.
     * <p>
     * After the {@code finalize} method has been invoked for an object, no
     * further action is taken until the Java virtual machine has again
     * determined that there is no longer any means by which this object can
     * be accessed by any thread that has not yet died, including possible
     * actions by other objects or classes which are ready to be finalized,
     * at which point the object may be discarded.
     * <p>
     * The {@code finalize} method is never invoked more than once by a Java
     * virtual machine for any given object.
     * <p>
     * Any exception thrown by the {@code finalize} method causes
     * the finalization of this object to be halted, but is otherwise
     * ignored.
     *
     * @throws Throwable the {@code Exception} raised by this method
     * @see java.lang.ref.WeakReference
     * @see java.lang.ref.PhantomReference
     * @jls 12.6 Finalization of Class Instances
     */
protected void finalize() throws Throwable { }  
     

梳理一下上面規(guī)范講述的幾點

  • 訪問垃圾收集在對象上當垃圾收集這確定這個對象上沒有更多的引用時可能會觸發(fā)finalize方法
  • 一個子類重寫了finalize方法處理系統(tǒng)資源或者執(zhí)行其它的清理也就是調(diào)用System.gc可能會觸發(fā)
  • 這個一般的合約規(guī)定finalize,如果Java虛擬機已經(jīng)確定這不再有任何意味這個對象能通過任何一個尚未死亡的線程訪問的方法調(diào)用仑濒,除非是由于最后確定的其它對象或類的準備工作所采取的行動.
  • finalize方法可以采取任何行動,包括使此對象再次可用于其它線程,finalize的通常是在對象不可撤銷地丟棄之前執(zhí)行清楚動作.例如:表示輸入輸出連接的對象的finalize方法可能會在對象被永久丟棄之前執(zhí)行顯式I/O事務來中斷連接
    Object中finalize操作只是返回一個正常線程
  • Java規(guī)范確保調(diào)用finalize的線程在調(diào)用finalize方法時不會持有任何用戶可見的同步鎖
  • 如果finalize方法拋出未捕獲的異常,則會忽略該異常,并終止該對象的定類。
  • finalize方法不會被任何對象調(diào)用多次
  • finalize方法拋出的任何異常都會導致該對象的終止被停止,否則就忽略

針對上述規(guī)范,我有以下幾點疑惑

finalize到底是使用在什么應用場景

通常我們知道對象創(chuàng)建完,要做清理操作,當然GC會清理哪些由new分配的內(nèi)存,但是如果不是通過new分配的內(nèi)存清理的話,就需要調(diào)用finalize方法.
它的工作原理:一旦垃圾回收器準備釋放對象占用的內(nèi)存空間,將首先調(diào)用finalize方法,并且在下一次垃圾回收動作發(fā)生,才會真正的回收該對象占用的內(nèi)存,也就是finalize方法會在垃圾回收器真正回收對象之前調(diào)用

finalize到底是不是C++中的析構(gòu)函數(shù)

在C++中銷毀對象必須用到析構(gòu)函數(shù),且兌現(xiàn)一定會被銷毀(如果程序沒有缺陷)偷遗,但是Java里的對象并非總是被回收.也就是:

  • 對象有可能沒有被垃圾回收
  • 垃圾回收并不是等于析構(gòu)(因為析構(gòu)一定會銷毀對象)

我們使用finalize這個方法有時候是為了確保某個對象已經(jīng)被清楚墩瞳,我們自己手動的去清除這個對象.
一般只要程序沒有瀕臨儲存空間用完的那一刻,對象占用的存儲空間就總也得不到釋放.如果這個程序結(jié)束了,垃圾回收器一直沒有釋放掉你創(chuàng)建的任何對象的存儲空間,則隨著程序的退出,那些資源也會全部交還給操作系統(tǒng).個人覺得這個操作策略是正確的,能不用垃圾回收去處理就不出來,畢竟就省去了這部分開銷。
所以finalize并不會確保對象會被銷毀,它不是析構(gòu)函數(shù).

finalize另外一個用途(判斷對象在清理時是否安全釋放)

前面已經(jīng)說過它可能是用來清理一些不是用過new創(chuàng)建的內(nèi)存對象,那么這些對象就是指的是Java中的本地方法創(chuàng)建的對象

無論是垃圾回收還是終結(jié)方法(finalize)都不能不保證一定會發(fā)生,因為它們發(fā)生的條件是對象被回收(這個條件是比較苛刻的氏豌,JVM只有在瀕臨內(nèi)存耗盡的情況下才會觸發(fā))

finalize可能會用于對象終結(jié)條件的驗證:
我們可以用finaliz來檢測對象被清理之前是不是還有什么操作沒有執(zhí)行,比如當某個對象打開了一個文件,在對象被回收之前程序應該關閉這個文件喉酌。使用finalize我們可以確保對象對安全的釋放掉了.
下面看finalize一個用于檢驗對相關是否安全釋放的例子:

package com;

/**
 * Created by XMl on 2017/9/8.
 */
public class Book {

    public boolean checkedOut = false;

    public Book(boolean checkedOut) {
//        checkedOut = checkedOut;
        this.checkedOut = checkedOut;
    }


    public void checkIn() {
        checkedOut = false;
    }

    /**
     * 重寫finalize方法
     *
     * @throws Throwable
     */
    @Override
    protected void finalize() throws Throwable {
        //校驗checkedOut
        if (checkedOut) {
            System.out.println("校驗出現(xiàn)了一次錯誤: Checked out ");
        }

//        super.finalize();
    }





}

我們寫一測試類
package com.rtti.xml;

import com.Book;

/**
 * Created by XMl on 2017/9/8.
 */
public class TerminationCondition {



    public static void main(String[] args) {

        Book novel = new Book(true);
        novel.checkIn();

        //對checked進行了一次誤操作
        new Book(true);

        //調(diào)用Gc 強制執(zhí)行終結(jié)操作(finalize)
        System.gc();





    }
}



打印信息:

image.png

我們看到輸出校驗信息.但是我們調(diào)用System.gc的時候并沒有回收對象內(nèi)存

總結(jié):

  • 垃圾回收內(nèi)存是JVM的一個不確定操作,通常會在系統(tǒng)瀕臨內(nèi)存溢出可能會回收,所以你不要指望垃圾回收來控制finalize方法的調(diào)用
  • finalize方法通常是用于清理一些非本地方法(native),和一些對象安全釋放校驗的操作
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泵喘,一起剝皮案震驚了整個濱河市泪电,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌涣旨,老刑警劉巖歪架,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異霹陡,居然都是意外死亡和蚪,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門烹棉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來攒霹,“玉大人,你說我怎么就攤上這事浆洗〈呤” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵伏社,是天一觀的道長抠刺。 經(jīng)常有香客問我,道長摘昌,這世上最難降的妖魔是什么速妖? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮聪黎,結(jié)果婚禮上罕容,老公的妹妹穿的比我還像新娘。我一直安慰自己稿饰,他們只是感情好锦秒,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著喉镰,像睡著了一般旅择。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上侣姆,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天砌左,我揣著相機與錄音脖咐,去河邊找鬼。 笑死汇歹,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的偿凭。 我是一名探鬼主播产弹,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼弯囊!你這毒婦竟也來了痰哨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤匾嘱,失蹤者是張志新(化名)和其女友劉穎斤斧,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霎烙,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡撬讽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了悬垃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片游昼。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖尝蠕,靈堂內(nèi)的尸體忽然破棺而出烘豌,到底是詐尸還是另有隱情,我是刑警寧澤看彼,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布廊佩,位于F島的核電站,受9級特大地震影響靖榕,放射性物質(zhì)發(fā)生泄漏标锄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一序矩、第九天 我趴在偏房一處隱蔽的房頂上張望鸯绿。 院中可真熱鬧,春花似錦簸淀、人聲如沸瓶蝴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舷手。三九已至,卻和暖如春劲绪,著一層夾襖步出監(jiān)牢的瞬間男窟,已是汗流浹背盆赤。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留歉眷,地道東北人牺六。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像汗捡,于是被迫代替她去往敵國和親淑际。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1.什么是垃圾回收扇住? 垃圾回收(Garbage Collection)是Java虛擬機(JVM)垃圾回收器提供...
    簡欲明心閱讀 89,501評論 17 311
  • 1. 垃圾回收的意義在C++中春缕,對象所占的內(nèi)存在程序結(jié)束運行之前一直被占用,在明確釋放之前不能分配給其它對象艘蹋;而在...
    愛情小傻蛋閱讀 935評論 0 11
  • 一. 垃圾回收的意義 在C++中锄贼,對象所占的內(nèi)存在程序結(jié)束運行之前一直被占用,在明確釋放之前不能分配給其它對...
    Stan_Z閱讀 1,932評論 0 25
  • Java 面試題 整理自牛客網(wǎng) 什么是Java虛擬機强品?為什么Java被稱作是“平臺無關的編程語言”膘侮? Java虛擬...
    GuaKin_Huang閱讀 10,668評論 19 265
  • 輕紗流水半漂泊 流年墨色對與酌 不知誰問多情與 無情深處自難得 2017.5.3
    雪魄黎已閱讀 195評論 0 2