日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

AJPFX讲解Java 性能优化[4]:关于 finalize 函数

發(fā)布時(shí)間:2023/12/15 java 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AJPFX讲解Java 性能优化[4]:关于 finalize 函数 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

★finalize 函數(shù)的調(diào)用機(jī)制

  俺經(jīng)常啰嗦:“了解本質(zhì)機(jī)制的重要性”。所以今天也得先談?wù)?finalize 函數(shù)的調(diào)用機(jī)制。在聊之前,先聲明一下:Java虛擬機(jī)規(guī)范(見“這里”),并沒有硬性規(guī)定垃圾回收該不該搞,以及該如何搞。所以俺這里提到的 finalize 函數(shù)的調(diào)用機(jī)制,或許適用于大多數(shù) JVM,但【不保證】適用于所有的 JVM。

◇何時(shí)被調(diào)用?

  finalize 啥時(shí)候才會(huì)被調(diào)用捏?一般來說,要等到JVM開始進(jìn)行垃圾回收的時(shí)候,它才【有可能】被調(diào)用。而 JVM 進(jìn)行垃圾回收的時(shí)間點(diǎn)是【非常】不確定的,依賴于各種運(yùn)行時(shí)的環(huán)境因素。具體細(xì)節(jié)可以參見“本系列前一帖”。正是由于 finalize 函數(shù)調(diào)用時(shí)間點(diǎn)的不確定,導(dǎo)致了后面提到的某些缺點(diǎn)。

◇誰來調(diào)用?

  說完何時(shí)調(diào)用,咱接著來聊一下被誰調(diào)用?
  常見的 JVM 會(huì)通過 GC 的垃圾回收線程來進(jìn)行 finalize 函數(shù)的調(diào)用。由于垃圾回收線程比較重要(人家好歹也是 JVM 的一個(gè)組成部分嘛),為了防止 finalize 函數(shù)拋出的異常影響到垃圾回收線程的運(yùn)作,垃圾回收線程會(huì)在調(diào)用每一個(gè) finalize 函數(shù)時(shí)進(jìn)行 try/catch,如果捕獲到異常,就直接丟棄,然后接著處理下一個(gè)失效對(duì)象的 finalize 函數(shù)。

★對(duì) finalize 函數(shù)的誤解和誤用

◇把 finalize 理解為“析構(gòu)函數(shù)”

  學(xué)過 C++ 的同學(xué)應(yīng)該都知道“析構(gòu)函數(shù)”(不懂 C++ 的同學(xué)直接跳過此小節(jié))。C++ 析構(gòu)函數(shù)是在對(duì)象離開作用域的當(dāng)口,【立即】被調(diào)用的。
  很多從 C++ 轉(zhuǎn) Java 的同學(xué)會(huì)想當(dāng)然地把 Java 的 finalize 函數(shù)牽強(qiáng)附會(huì)成 C++ 的析構(gòu)函數(shù)(兩者確實(shí)有某些相似之處)。然而,現(xiàn)實(shí)往往不是這么美好滴。由于 Java 的 finalize 函數(shù)和 C++ 的析構(gòu)函數(shù)之間有許多非常【關(guān)鍵性】的差異,那些把 finalize 拿來當(dāng)析構(gòu)函數(shù)用的同學(xué),是注定要碰壁滴(具體請(qǐng)看本文后面“finalize 函數(shù)的缺點(diǎn)”)。

◇依靠 finalize 來釋放資源

  很多同學(xué)寄希望于通過 finalize() 來完成類對(duì)象中某些資源的釋放(比如關(guān)閉數(shù)據(jù)庫連接之類)。
  有這種企圖的同學(xué),請(qǐng)注意看本文后面的“finalize 函數(shù)的缺點(diǎn)”!

★使用 finalize 函數(shù)的注意事項(xiàng)

  下面介紹的注意事項(xiàng),有些可能和性能優(yōu)化關(guān)系不大,俺也一并列出來。

◇調(diào)用時(shí)間不確定——有資源浪費(fèi)的風(fēng)險(xiǎn)

  前面已經(jīng)介紹了調(diào)用機(jī)制。同學(xué)們應(yīng)該認(rèn)清【finalize 的調(diào)用時(shí)機(jī)是很不確定的】這樣一個(gè)事實(shí)。所以,假如你把某些稀缺資源放到 finalize() 中釋放,可能會(huì)導(dǎo)致該稀缺資源等上很久很久很久以后才被釋放。這可是資源的浪費(fèi)啊!
  另外,某些類對(duì)象所攜帶的資源(比如某些 JDBC 的類)可能本身就很耗費(fèi)內(nèi)存,這些資源的延遲釋放會(huì)造成很大的性能問題。

◇可能不被調(diào)用——有資源泄漏的風(fēng)險(xiǎn)

  很多同學(xué)誤以為 finalize() 總是會(huì)被調(diào)用,【其實(shí)不然】。在某些情況下,finalize() 壓根兒不被調(diào)用。比如在 JVM 退出的當(dāng)口,內(nèi)存中那些對(duì)象的 finalize 函數(shù)可能就不會(huì)被調(diào)用了。
  俺估摸著:還有同學(xué)在打 “runFinalizersOnExit” 的主意,來確保所有的 finalize 在 JVM 退出前被調(diào)用。但是,很可惜也很遺憾,該方法從 JDK 1.2 開始,就已經(jīng)被廢棄了。即使該方法不被廢棄,也是有很大的線程安全隱患滴!企圖打這個(gè)主意的同學(xué),趁早死了這條心吧!
  從上述可以看出,一旦你依賴 finalize() 來幫你釋放資源,那可是很不妙啊(【有資源泄漏的危險(xiǎn)】)!關(guān)于資源泄漏的嚴(yán)重性,俺在“這里”曾經(jīng)提到過。很多時(shí)候,資源泄露導(dǎo)致的性能問題更加嚴(yán)重,萬萬不可小看。

◇對(duì)象可能在 finalize 函數(shù)調(diào)用時(shí)復(fù)活——有詐尸的風(fēng)險(xiǎn)

  詐尸的情況比較少見,不過俺還是稍微提一下。
  本來,只有當(dāng)某個(gè)對(duì)象已經(jīng)失效(沒有引用),垃圾回收器才會(huì)調(diào)用該對(duì)象的 finalize 函數(shù)。但是,萬一碰上某個(gè)變態(tài)的程序員,在 finalize() 函數(shù)內(nèi)部再把對(duì)象自身的引用(也就是 this)重新保存在某處,也就相當(dāng)于把自己復(fù)活了(因?yàn)檫@個(gè)對(duì)象重新有了引用,不再處于失效狀態(tài))。這種做法是不是夠變態(tài)啊 :-)
  為了防止發(fā)生這種詭異的事情,垃圾回收器只能在每次調(diào)用完 finalize() 之后再次去檢查該對(duì)象是否還處于失效狀態(tài)。這無形中又增加了 JVM 的開銷。
  隨便提一下。由于 JDK 的文檔中規(guī)定了(具體參見“這里”),JVM 對(duì)于每一個(gè)類對(duì)象實(shí)例最多只會(huì)調(diào)用一次 finalize()。所以,對(duì)于那些詐尸的實(shí)例,當(dāng)它們真正死亡時(shí),finalize() 反而不會(huì)被調(diào)用了。這看起來是不是很奇怪?

◇要記得自己做異常捕獲

  剛才在介紹 finalize() 調(diào)用機(jī)制時(shí)提到,一旦有異常拋出到 finalize 函數(shù)外面,會(huì)被垃圾回收線程捕獲并丟棄。也就是說,異常被忽略掉了(異常被忽略的危害,“這里”有提到)。為了防止這種事兒,凡是 finalize() 中有可能拋出異常的代碼,你都得寫上 try catch 語句,自己進(jìn)行捕獲。

◇要小心線程安全

  由于調(diào)用 finalize() 的是垃圾回收線程,和你自己代碼的線程不是同一個(gè)線程;甚至不同對(duì)象的 finalize() 可能會(huì)被不同的垃圾回收線程調(diào)用(比如使用“并行收集器”的時(shí)候)。所以,當(dāng)你在 finalize() 里面訪問某些數(shù)據(jù)的時(shí)候,還得時(shí)刻留心線程安全的問題。

★結(jié)論

  前面廢了這么多話,最后稍微總結(jié)一下。俺竊以為:finalize 實(shí)在是 Java 的雞肋。或許它對(duì)于【極少數(shù)】程序員有用,但對(duì)于大多數(shù)人(包括俺自個(gè)兒),這玩意兒壓根兒沒啥好處。大伙兒還是盡量不用為妙。

轉(zhuǎn)載于:https://blog.51cto.com/14314113/2388466

總結(jié)

以上是生活随笔為你收集整理的AJPFX讲解Java 性能优化[4]:关于 finalize 函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。