java终结器_Java的终结器仍然存在
java終結(jié)器
當(dāng)我第一次學(xué)習(xí)Java并從C ++過(guò)渡到Java時(shí),我記得我經(jīng)常被告知,經(jīng)常讀到它不應(yīng)該像C ++析構(gòu)函數(shù)那樣對(duì)待Java終結(jié)器,也不應(yīng)該依靠它。 該建議的頻率和堅(jiān)持性對(duì)我產(chǎn)生了影響,以至于我無(wú)法回憶起我上一次編寫(xiě)finalize()方法的經(jīng)歷,也無(wú)法回憶起我在編寫(xiě),閱讀,審閱,維護(hù),修改和調(diào)試的Java代碼。 但是直到最近,我還沒(méi)有考慮finalize()的影響 ,可能是因?yàn)槲覜](méi)有使用finalize() 。 最近對(duì)finalize()的經(jīng)驗(yàn)已將Java終結(jié)器的效果從“學(xué)術(shù)練習(xí)”轉(zhuǎn)變?yōu)椤耙巴狻钡恼鎸?shí)問(wèn)題。
Object.finalize()的方法級(jí)Javadoc文檔注釋提供了有關(guān)Java終結(jié)器的一些有趣的細(xì)節(jié)。 首先提供對(duì)方法的總體描述,“當(dāng)垃圾回收確定不再有對(duì)該對(duì)象的引用時(shí),垃圾回收器將其調(diào)用在對(duì)象上。 子類(lèi)會(huì)覆蓋finalize方法來(lái)處置系統(tǒng)資源或執(zhí)行其他清理。” 該Javadoc注釋的另一部分警告了與Java終結(jié)器的使用通常相關(guān)的幾個(gè)問(wèn)題 :“ Java編程語(yǔ)言不能保證哪個(gè)線(xiàn)程將為任何給定對(duì)象調(diào)用finalize方法。 但是,可以保證,調(diào)用finalize的線(xiàn)程在調(diào)用finalize時(shí)不會(huì)持有任何用戶(hù)可見(jiàn)的同步鎖。 如果finalize方法引發(fā)了未捕獲的異常,則該異常將被忽略,并且該對(duì)象的終結(jié)將終止。”
喬什·布洛赫(Josh Bloch)在《 有效的Java》中專(zhuān)門(mén)介紹了Java終結(jié)器這一主題。 Effective Java第二版的第7項(xiàng)標(biāo)題簡(jiǎn)潔明了,“避免終結(jié)器”。 盡管有效Java中的許多項(xiàng)目都使用了動(dòng)詞,例如“ Prefer”或“ Consider”,但該項(xiàng)目使用了更強(qiáng)的動(dòng)詞“ Avoid”。 布洛赫(Bloch)確實(shí)列舉了一些可能使用終結(jié)器的示例,但是他對(duì)仍然存在的內(nèi)在問(wèn)題的描述以及為減輕這些問(wèn)題而需要考慮的許多事情,使我們大多數(shù)人都盡量避免使用它們。
Bloch以強(qiáng)調(diào)的( 粗體 )語(yǔ)句開(kāi)始了有效的Java項(xiàng)目“ Avoid Finalizers”,“ Finalizers是不可預(yù)測(cè)的,通常是危險(xiǎn)的,并且通常是不必要的。 “ Bloch強(qiáng)調(diào)開(kāi)發(fā)人員不應(yīng)“ 在終結(jié)器中做任何對(duì)時(shí)間要求嚴(yán)格的事情 ”,因?yàn)椤安荒鼙WC[Java終結(jié)器將被立即執(zhí)行”,并且他強(qiáng)調(diào)開(kāi)發(fā)人員應(yīng)“ 永遠(yuǎn)不要依賴(lài)終結(jié)器來(lái)更新關(guān)鍵的持久狀態(tài) ”。因?yàn)椤案緹o(wú)法保證[Java終結(jié)器]將被執(zhí)行。” Bloch引用了終結(jié)器中的異常不會(huì)被捕獲,并警告了這樣做的危險(xiǎn),因?yàn)椤拔床东@的異常可能會(huì)使對(duì)象處于損壞狀態(tài)。”
Bloch還描述了我最近使用過(guò)的Java終結(jié)器的負(fù)面影響。 他的“避免終結(jié)器”項(xiàng)強(qiáng)調(diào)(以粗體顯示 ),“ 使用終結(jié)器會(huì)導(dǎo)致嚴(yán)重的性能損失 ”,因?yàn)椤?使用終結(jié)器創(chuàng)建和銷(xiāo)毀對(duì)象”會(huì)花費(fèi)更長(zhǎng)的時(shí)間。 在我們的例子中,我們使用的是第三方庫(kù),該庫(kù)在內(nèi)部使用Java類(lèi)finalize()方法來(lái)釋放本機(jī)內(nèi)存(C / C ++通過(guò)JNI )。 因?yàn)檫@些類(lèi)中有很多這些對(duì)象帶有finalize()方法,所以似乎處理Java終結(jié)的系統(tǒng)線(xiàn)程落后了,并且鎖定了正在終結(jié)的對(duì)象。
垃圾收集也受到了不利影響 ,因?yàn)槭占邌?dòng)的頻率比我們通常看到的還要頻繁。 我們很快意識(shí)到垃圾收集日志表明垃圾收集問(wèn)題,這些問(wèn)題很難追溯到典型的堆大小問(wèn)題或我們自己類(lèi)的內(nèi)存泄漏 。 使用jcmd <pid> GC.class_histogram GC.class_histogram對(duì)JVM進(jìn)程運(yùn)行非常有用的jcmd ,有助于我們快速了解潛在的罪魁禍?zhǔn)住?該類(lèi)直方圖顯示了足夠的java.lang.ref.Finalizer實(shí)例,以確保它在頂部排名第三。 由于該課程通常在課程直方圖的下方,因此我什至通常不會(huì)看到或考慮它。 當(dāng)我們意識(shí)到在類(lèi)直方圖中描述的前八個(gè)實(shí)例中的另外三個(gè)是第三方庫(kù)中的三個(gè)類(lèi),并且它們實(shí)現(xiàn)了finalize()方法時(shí),我們就能夠解釋行為并將其歸咎于終結(jié)器 (四個(gè)直方圖中排名前八位的類(lèi)別中,這是一個(gè)相當(dāng)安全的指責(zé))。
Java語(yǔ)言規(guī)范在第12.6節(jié) (“類(lèi)實(shí)例的完成”)中提供了一些與Java終結(jié)器相關(guān)的細(xì)節(jié)。 本節(jié)從描述Java終結(jié)器開(kāi)始:“可以為對(duì)象調(diào)用的finalize()的特定定義稱(chēng)為該對(duì)象的終結(jié)器。 在垃圾回收器回收對(duì)象的存儲(chǔ)之前,Java虛擬機(jī)將調(diào)用該對(duì)象的終結(jié)器。” 這里引用了Java語(yǔ)言規(guī)范這一節(jié)中描述的Java終結(jié)器的一些有意不確定的特征(我已經(jīng)加了任何強(qiáng)調(diào) ):
- “Java編程語(yǔ)言沒(méi)有規(guī)定如何盡快終結(jié)將被調(diào)用。”
- “ Java編程語(yǔ)言沒(méi)有指定哪個(gè)線(xiàn)程將為任何給定對(duì)象調(diào)用終結(jié)器。”
- “終結(jié)器可以按任何順序調(diào)用,甚至可以同時(shí)調(diào)用。”
- “如果在完成過(guò)程中拋出未捕獲的異常 ,則該異常將被忽略,并且該對(duì)象的完成將終止。”
我發(fā)現(xiàn)自己很喜歡與解決此問(wèn)題的團(tuán)隊(duì)一起工作,因?yàn)槲夷軌蛟凇艾F(xiàn)實(shí)生活”中體驗(yàn)我只是從“學(xué)術(shù)”意義上閱讀和了解的內(nèi)容。 應(yīng)用最喜歡的工具(例如jcmd )并應(yīng)用以前的經(jīng)驗(yàn)(例如識(shí)別出jcmd 類(lèi)直方圖中看起來(lái)不合適的東西 )來(lái)解決一個(gè)新問(wèn)題總是很令人滿(mǎn)意的。
翻譯自: https://www.javacodegeeks.com/2017/03/javas-finalizer-still.html
java終結(jié)器
總結(jié)
以上是生活随笔為你收集整理的java终结器_Java的终结器仍然存在的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: (内保三备案)
- 下一篇: java 多模块模块变灰色_到底谁需要J