JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Software Design » Effective Java  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
本主題所含的標籤
作者 [Effective Java] 條款6 : 避免使用 finalizers (終結式) [精華]
metavige

麥塔.米奇

版主

發文: 2133
積分: 10
於 2003-10-03 15:45 user profilesend a private message to usersend email to metavigereply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
Finalizers (終結式)不可預期, 因此往往帶有危險, 而且往往並非必要
老實說
在書中看到這句話
真是有點 Shock !!!
從來沒想到會有這樣的情況 Black Eye
但是再繼續看下去, 我大概瞭解為什麼會這樣說了
-----------------------------------------------------------------------------------
通常
Java 程式設計師會以 try-finally 來達成一些資源回收的動作
但是
沒有任何保證提及 finalizers 會被準時(及時)執行[JLS,12.6]
當在 finalizer 進行一些跟時間有絕對關連的任務
比如說像是檔案的關閉
如果 finalizer 沒有及時關閉, 這樣子如果有下一個程式來存取檔案
就會發生錯誤

「及時執行 finalizer」正是垃圾回收演算法的主要功能之一
但是程式的行為如果取決於 finalizer 的及時性
可能會變的不穩定
然後就有可能有一種在專案過程中常發生的一種「正常現象」

客戶:為什麼你的程式有問題? 你不是告訴我說你昨天改好了嗎? Angry
PG: 對阿, 我昨天明明改好了, 我在我自己的機器上面測試也可以阿?
為什麼到這邊就不行了呢? Stupid
客戶:這我哪知道??? 你們每次都這樣......
(以下省略三千八百六十七句罵人的話.....)
客戶:反正我現在看就是不行, 你就是要幫我改好.....管你搞到幾點 !!!
PG: Black Eye ---> (心裡的話: EnvelopeEnvelopeEnvelope)

JLS 規格書不保證 finalizer 被及時執行, 也不保證他們終將被執行
因此絕對(真的嗎Stupid) 不能倚賴 finalizer 更改關鍵的(重要的)永續狀態 (persistent state)

如果一個未被捕捉的異常在 finalization 其間被拋出, 該異常將被忽略
而物件的 finalization 亦將結束 [JLS, 12.6]


而那些「物件會封裝某些資源(如檔案或執行緒), 而資源必須被歸還」的 class
只要提供一個「明確終結函式」(explicit termination method), 並要求客戶一旦不需要該 class 的任何實體就喚起該函式
Ex: InputStream.close() or java.util.Timer.close()

那 finalizer 到底有什麼功能?
1. 作為一個安全網, 如果忘記呼叫你所提供的「明確終結函式」
2. 如果 native peer 不持有關鍵資源的話, 則 finalizer 就是用來執行 native peer 的回收
native peers(原生同等物) - 「正常物件藉著 native method 而委託」的一個 native object 老實說.....不懂

finalizer chaining 並不會被自動執行
如果在 class 內有一個 finalizer, 而 subclass 覆寫了它
subclass finalizer 必須手動喚起 superclass finalizer

如果 subclass 不夠嚴謹, 忘記呼叫 superclass finalizer
要防止這樣的動作, 就是為每一個被終結物件創建一個額外物件
這時候就會將終結處理放在一個 anonymous class(匿名類別 ,條款18), 這樣的 class 的實體我們稱為 finalizer guardian

以下的 Code 是參考 [Effective Java]
1
2
3
4
5
6
7
8
9
10
11
//Finalizer Guardian idiom
public class Foo {
  //Sole purpose of this object is to finalize outer Foo object
  private final Object finalizerGuardian = new Object() {
    protected void finalize() throws Throwable {
      // Finalize outer Foo object
      .....
    }
  };
  .. //Remainer omitted
}


reply to postreply to post
請各位新手參考 論壇規範Java 新手 FAQ
作者 Re:[Effective Java] 條款6 : 避免使用 finalizers (終結式) [Re:metavige]
ymshin





發文: 277
積分: 4
於 2003-10-03 21:27 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
finalizer 是否執行取決於 JVM, 各平台的 JVM 雖均依照 spec. implement, 行為還是不一致(implement 使用的演算法不同), finalizer 執行時間可能不一樣(或是根本從未執行), 所以 finalizer 寫的程式到了另一台機器, 可能因為 JVM 平台或版本不同而產生不同結果, 所謂的不穩定原因在此.

Ex: InputStream.close() or java.util.Timer.close()


嗯嗯嗯...Timer...有 close() 嗎? Big Smile


1. 作為一個安全網, 如果忘記呼叫你所提供的「明確終結函式」
2. 如果 native peer 不持有關鍵資源的話, 則 finalizer 就是用來執行 native peer 的回收


這兩點指的應該是何時使用 finalizer, 而不是指 finalizer 的功能, native object 指的是 java 以外的語言產生的 object, 像是
call c/c++ native function create 的 objects; JNI 不熟, 不過相關文章應該俯拾皆有. ^^


如果 subclass 不夠嚴謹, 忘記呼叫 superclass finalizer

你忘記寫下一句耶~~~ 會怎樣咧? @@


ymshin edited on 2003-10-03 21:55
reply to postreply to post
作者 Re:[Effective Java] 條款6 : 避免使用 finalizers (終結式) [Re:ymshin]
metavige

麥塔.米奇

版主

發文: 2133
積分: 10
於 2003-10-03 23:39 user profilesend a private message to usersend email to metavigereply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
ymshin wrote:
嗯嗯嗯...Timer...有 close() 嗎? Big Smile


呵呵, 還是有"手"誤
OK, 應該是 java.util.Timer.cancel()


你忘記寫下一句耶~~~ 會怎樣咧? @@

會.....五雷轟頂, 不得好死..... 哈哈哈哈哈哈....... Devil


reply to postreply to post
請各位新手參考 論壇規範Java 新手 FAQ
作者 Re:[Effective Java] 條款6 : 避免使用 finalizers (終結式) [Re:metavige]
ymshin





發文: 277
積分: 4
於 2003-10-04 15:27 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
metavige wrote:
會.....五雷轟頂, 不得好死..... 哈哈哈哈哈哈....... Devil


可能沒錯啦, 不過重要的是 subclass 忘記呼叫 superclass finalizer 的話會產生什麼後果咧?


reply to postreply to post
作者 Re:[Effective Java] 條款6 : 避免使用 finalizers (終結式) [Re:ymshin]
popcorny

Jakarta 2%

版主

發文: 752
積分: 20
於 2003-10-04 15:50 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
ymshin wrote:
可能沒錯啦, 不過重要的是 subclass 忘記呼叫 superclass finalizer 的話會產生什麼後果咧?

那finlizer這裡如果有一些重要的釋放資源的邏輯
就完全不會被呼叫到...(因為已經被override了)

還有很多書上都有說
不要把finalize跟c++的destructor混文一談
兩個是完全不一樣的東西


reply to postreply to post
作者 Re:[Effective Java] 條款6 : 避免使用 finalizers (終結式) [Re:popcorny]
Duncan

還隱隱作痛

版主

發文: 7816
積分: 39
於 2003-10-05 00:20 user profilesend a private message to usersend email to Duncanreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
popcorny wrote:
還有很多書上都有說
不要把finalize跟c++的destructor混文一談
兩個是完全不一樣的東西


如果 finalizer 一定會執行,可以試著討論一下 destructor(特別是 virtual destructor)和 finalizer 的差異嗎?除了 destructor 不需要明白喚起 base class destructor 之外,還有哪些差異呢?


reply to postreply to post

給我
辣味豆腐 其餘免談
作者 Re:[Effective Java] 條款6 : 避免使用 finalizers (終結式) [Re:ymshin]
metavige

麥塔.米奇

版主

發文: 2133
積分: 10
於 2003-10-06 11:15 user profilesend a private message to usersend email to metavigereply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
ymshin wrote:
可能沒錯啦, 不過重要的是 subclass 忘記呼叫 superclass finalizer 的話會產生什麼後果咧?


之前是開玩笑的話啦
其實如果沒有呼叫 finalizer 的話

如果有資源需要回收, 而是撰寫在 finalizer 裡面的話
就會造成資源無法回收
比如說檔案資源的關閉

最嚴重的 , 當然就是系統掛掉了, 因為資源無法回收啦
不過這要看你是怎樣寫的


reply to postreply to post
請各位新手參考 論壇規範Java 新手 FAQ
作者 Re:[Effective Java] 條款6 : 避免使用 finalizers (終結式) [Re:metavige]
etman





發文: 15
積分: 0
於 2003-10-29 09:42 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
>>比如說像是檔案的關閉
>>如果 finalizer 沒有及時關閉, 這樣子如果有下一個程式來存取檔案
>>就會發生錯誤

檔案的關閉和物件的生命期應是兩回事喔!!,在你呼叫InputStream.close()時,他會直接將檔案關閉

再補充,關於Finalizer和Destructor這兩個不同的意義就在物件上,無論你是否有去覆寫finalize method他都不會馬上回收,這個方法是由Garbage collection呼叫,而通常會去覆寫此method都不是去做此類別的物件回收,而是當你透過JNI去呼叫C/C++時,把你呼叫而產生在C/C++裡的實例刪掉,這是以應用面來看,當然,或許每個人有不同的考量,但Destructor就不一樣,他是物件的解構式,所以當此方法被呼叫時,亦即代表物件的消失,JAVA的finalize被呼叫時,視實作廠商的不同而有不同的作法!!


etman edited on 2003-10-29 10:20
reply to postreply to post
作者 Re:[Effective Java] 條款6 : 避免使用 finalizers (終結式) [Re:Duncan]
alien

小弟劣作一幅



發文: 772
積分: 6
於 2004-06-24 16:37 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
Duncan wrote:
如果 finalizer 一定會執行,可以試著討論一下 destructor(特別是 virtual destructor)和 finalizer 的差異嗎?除了 destructor 不需要明白喚起 base class destructor 之外,還有哪些差異呢?


(很久以前的討論了 Tongue , 今天無意看到的, 好像蠻有趣所以順便回一回)

個人想得到的有:
1) C++ 中, 一旦進入 destructor, 該 object 已經被當成不存在了.
Java 不然.

2) 1 的補充, Java 中, object 在 finalizer 中可以復活 (resurrect),
而 resurrected 的 object 則不會再 invoke 其 finalizer. C++ 沒有
類似的機制 (關乎 gc 吧)

3) 由於 gc 的機制引起的分別, Java 的 finalizer 可以是 object lifetime
完結 (可以當成是 eligible for gc 吧?) 後不知何時才被 invoke. C++ 的
destructor 是object 的 lifetime 一完結就會被 invoke. 順便一提, C++
有很多很方便的 utility 都是靠這機制達成的 Smile

4) C++ 的 destructor 有 chainning, Java 沒有.

大概只能想到這些, 有人想得到更多嗎?


reply to postreply to post

public class Alien {
public boolean isNewbie() {
return true;
}
public String toString() {
return "請大家多多指教";
}
}
作者 Re:[Effective Java] 條款6 : 避免使用 finalizers (終結式) [Re:metavige]
robot2030





發文: 22
積分: 0
於 2004-11-09 14:08 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
請問最後一段的Finalizer Guardian是怎麼運作的,finalizerGuardian 要變成null才有機會執行finalize,這個finalizerGuardian=null;是在什麼時候去做的呢?還有它的用途或用法可以解釋一下嗎,看書上的說明看不懂?謝謝

robot2030 edited on 2004-11-09 15:33
reply to postreply to post
作者 Re:[Effective Java] 條款6 : 避免使用 finalizers (終結式) [Re:robot2030]
koji

秒速5センチメートル

站長

發文: 8415
積分: 19
於 2009-02-03 09:13 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
robot2030 wrote:
請問最後一段的Finalizer Guardian是怎麼運作的,finalizerGuardian 要變成null才有機會執行finalize,這個finalizerGuardian=null;是在什麼時候去做的呢?還有它的用途或用法可以解釋一下嗎,看書上的說明看不懂?謝謝

超晚回

因為他是Foo instance的成員
所以當Foo instance不被指到時,它也就有機會被GC了
然後就有可能被呼叫了..

koji


reply to postreply to post
JCConf Taiwan 2015 開始售票了!!
Facebook上的TWJUG社團,歡迎加入
作者 Re:[Effective Java] 條款6 : 避免使用 finalizers (終結式) [Re:metavige]
caterpillar

良葛格

版主

發文: 2613
積分: 70
於 2019-02-25 10:13 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
Java 9 廢棄了 finalize 方法,FileInputStream 等也清空了 finalize 方法的實作,改用 PhantomReference 的機制,JVM 有個執行緒會監控 Reference,在實例不再被參考時,呼叫 close 方法。

至於相容性的部份,若有 FileInputStream 的子類,且自定義了 close 方法,實例化時會有個 AltFinalizer 產生,AltFinalizer 建立時會包裹 FileInputStream,AltFinalizer 的作用就是等著被回收時,呼叫自定義的 finalize 方法(被加了 @SuppressWarnings("deprecation")),其中呼叫了 FileInputStream 的 close 方法。


reply to postreply to post
良葛格學習筆記
» JWorld@TW »  Software Design » Effective Java

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8