2014-03-13 64 views
4

我的應用程序使用了一些第三方庫(JTDS驅動程序),它有一些對象可以覆蓋finalize()方法。我認爲他們遵守關於什麼時候不使用finalize()的所有規則 - 它不依賴於及時或完全運行它們。Java不釋放finalize()覆蓋的對象

問題是,他們的對象永遠不會被釋放。它們似乎卡在Finalizer隊列中,並且從未刪除。它們在幾個星期內緩慢建立起來,並將JVM從堆空間運行。線程轉儲顯示終結器線程正在等待某些事件調用finalize()。如果我調用System.runFinalization(),則對象已完成並從終結器隊列中正確刪除(並且不再顯示在堆轉儲中)。

爲什麼System.runFinalization()會正確移除對象,但Finalizer線程不會自行完成它?

+0

我不明白爲了幫助你,有人會重現你的問題。 –

+1

您在啓動時將什麼參數傳遞給JVM? –

+0

除非你有這些finalize方法的代碼可用,你如何期待某個人完全幫助? – fge

回答

0

這意味着您的finalize()方法花費的時間太長,導致隊列中的對象在隊列中等待被調用。

對象在被調用時將從隊列中刪除,並且在被調用後不會在隊列中。

+1

但線程轉儲顯示終結線程剛剛等待,不參與運行其中一個終結方法?並在調用runFinalization時,它聽起來像是所有終結器都及時運行? –

+0

@GrahamGriffiths最可能的問題不是它看起來像什麼。注意:*所有對象完成後,必須調用GC來清理它們。 –

+0

對,@GrahamGriffiths,終結者線程在任何時候都沒有做任何事情,我可以在線程轉儲中捕獲它。 – Jason

0

爲什麼Finalizer線程不會刪除這些對象?

簡單的答案是,終結者身上的某些東西導致了死鎖。終結器是清理最糟糕的方式。它由垃圾收集器調用。

垃圾收集器 確定沒有更多的對象引用時,由對象上的垃圾回收器調用。 當垃圾收集器的對象有強烈的參考時會發生什麼?該對象永遠不會被垃圾收集器。我強烈懷疑這是你的情況發生了什麼。

約書亞·布洛克說,在有效的Java:

總之不要使用終結除了作爲安全網或終止 不重要的本土資源

避免終結 - 是終結不可預知,常常是危險的,並且通常是不必要的

http://www.informit.com/articles/article.aspx?p=1216151&seqNum=7

+0

終結器線程沒有死鎖。它只是在等待一些事情要做。圖書館作者正確使用finalize()方法作爲「安全網或終止非關鍵資源」。事實上,finalize()方法將要關閉的所有東西都已經關閉了。只是這個類重寫了finalize(),導致它被添加到終結器隊列中。 – Jason