Java禁止使用finalize方法
什么是finalize方法
finalize()方法被定義在Java.lang.Object類中,意味著所有的類都可以重載這個(gè)方法。java垃圾回收器只之道釋放那些經(jīng)由new分配的內(nèi)存,所以如果你的對(duì)象并非通過(guò)new獲得的內(nèi)存,那么垃圾回收器就不知道如何釋放該對(duì)象的內(nèi)存了。
為了應(yīng)對(duì)這種情況,java允許在類中重載java.lang.Object類中的finalize()方法。
它的工作原理:一旦垃圾回收器準(zhǔn)備好釋放對(duì)象占用的存儲(chǔ)空間,將首先調(diào)用其finalize()方法,并且在下一次垃圾回收動(dòng)作發(fā)生時(shí),才會(huì)真正回收對(duì)象占用的內(nèi)存。
finalize函數(shù)的調(diào)用機(jī)制
java虛擬機(jī)規(guī)范并沒(méi)有硬性規(guī)定垃圾回收該不該搞,以及該如何搞。所以這里提到的調(diào)用機(jī)制不能保證適合所有jvm。
何時(shí)被調(diào)用?
finalize啥時(shí)候才會(huì)被調(diào)用捏?一般來(lái)說(shuō),要等到JVM開(kāi)始進(jìn)行垃圾回收的時(shí)候,它才有可能被調(diào)用。而JVM進(jìn)行垃圾回收的時(shí)間點(diǎn)是非常不確定的,依賴于各種運(yùn)行時(shí)的環(huán)境因素。正是由于finalize函數(shù)調(diào)用時(shí)間點(diǎn)的不確定,導(dǎo)致了后面提到的某些缺點(diǎn)。
誰(shuí)來(lái)調(diào)用?
常見(jiàn)的JVM會(huì)通過(guò)GC的垃圾回收線程來(lái)進(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ù)。
為什么禁止使用finalize()
1.調(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ì)造成很大的性能問(wèn)題。
2.可能不被調(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)用了。
估計(jì)有同學(xué)在打“runFinalizersOnExit”的主意,來(lái)確保所有的finalize在JVM退出前被調(diào)用。很可惜也很遺憾,該方法從JDK 1.2開(kāi)始,就已經(jīng)被廢棄了。即使該方法不被廢棄,也是有很大的線程安全隱患滴!
從上述可以看出,一旦你依賴finalize()來(lái)幫你釋放資源,那可是很不妙?。ㄓ匈Y源泄漏的危險(xiǎn))!很多時(shí)候,資源泄露導(dǎo)致的性能問(wèn)題更加嚴(yán)重,萬(wàn)萬(wàn)不可小看。
3.對(duì)象可能在finalize函數(shù)調(diào)用時(shí)復(fù)活
本來(lái),只有當(dāng)某個(gè)對(duì)象已經(jīng)失效(沒(méi)有引用),垃圾回收器才會(huì)調(diào)用該對(duì)象的finalize函數(shù)。但是,萬(wàn)一碰上某個(gè)變態(tài)的程序員,在finalize()函數(shù)內(nèi)部再把對(duì)象自身的引用(也就是this)重新保存在某處,也就相當(dāng)于把自己復(fù)活了(因?yàn)檫@個(gè)對(duì)象重新有了引用,不再處于失效狀態(tài))。 為了防止發(fā)生這種詭異的事情,垃圾回收器只能在每次調(diào)用完finalize()之后再次去檢查該對(duì)象是否還處于失效狀態(tài)。這無(wú)形中又增加了JVM的開(kāi)銷。隨便提一下。由于JDK的文檔中規(guī)定了,JVM對(duì)于每一個(gè)類對(duì)象實(shí)例最多只會(huì)調(diào)用一次finalize()。所以,對(duì)于那些詐尸的實(shí)例,當(dāng)它們真正死亡時(shí),finalize()反而不會(huì)被調(diào)用了。這看起來(lái)是不是很奇怪?
4.要記得自己做異常捕獲
剛才在介紹finalize()調(diào)用機(jī)制時(shí)提到,一旦有異常拋出到finalize函數(shù)外面,會(huì)被垃圾回收線程捕獲并丟棄。也就是說(shuō),異常被忽略掉了(異常被忽略的危害,“這里”有提到)。為了防止這種事兒,凡是finalize()中有可能拋出異常的代碼,你都得寫上try catch語(yǔ)句,自己進(jìn)行捕獲。
5.小心線程安全
由于調(diào)用finalize()的是垃圾回收線程,和你自己代碼的線程不是同一個(gè)線程;甚至不同對(duì)象的finalize()可能會(huì)被不同的垃圾回收線程調(diào)用(比如使用“并行收集器”的時(shí)候)。所以,當(dāng)你在finalize()里面訪問(wèn)某些數(shù)據(jù)的時(shí)候,還得時(shí)刻留心線程安全的問(wèn)題。
總結(jié)
以上所述是小編給大家介紹的Java禁止使用finalize方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
MyBatis-Plus插件機(jī)制及通用Service新功能
這篇文章主要介紹了MyBatis-Plus插件機(jī)制以及通用Service、新功能,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07JAVA?biginteger類bigdecimal類的使用示例學(xué)習(xí)
這篇文章主要為大家介紹了JAVA?biginteger類bigdecimal類的使用示例學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07詳解Springboot-MyBatis配置-配置端口號(hào)與服務(wù)路徑(idea社區(qū)版2023.1.4+apache-mav
這篇文章主要介紹了Springboot-MyBatis配置-配置端口號(hào)與服務(wù)路徑(idea社區(qū)版2023.1.4+apache-maven-3.9.3-bin),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07Java用Cookie限制點(diǎn)贊次數(shù)(簡(jiǎn)版)
最近做了一個(gè)項(xiàng)目,其中有項(xiàng)目需求是,要用cookie實(shí)現(xiàn)限制點(diǎn)贊次數(shù),特此整理,把實(shí)現(xiàn)代碼分享給大家供大家學(xué)習(xí)2016-02-02spring帶bean和config如何通過(guò)main啟動(dòng)測(cè)試
這篇文章主要介紹了spring帶bean和config,通過(guò)main啟動(dòng)測(cè)試,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07Java開(kāi)發(fā)環(huán)境配置JDK超詳細(xì)整理(適合新手入門)
這篇文章主要給大家介紹了關(guān)于Java開(kāi)發(fā)環(huán)境配置JDK超詳細(xì)整理的相關(guān)資料,非常適合新手入門,JDK是Java語(yǔ)言的軟件開(kāi)發(fā)工具包,主要用于移動(dòng)設(shè)備、嵌入式設(shè)備上的java應(yīng)用程序,需要的朋友可以參考下2023-11-11