2009-12-10 60 views
9

背景如何解決擺動監聽器內存泄漏?

所以我讀了Swing應用程序中經常內存泄漏因使用不同的聽衆(鼠標,鍵盤,焦點等)的起源。本質上,因爲你將一個對象註冊爲一個監聽器,並忘記註銷該對象,通知器最終會保持對象的引用,並泄漏一些內存。

我知道我們的應用程序沒有註銷的聽衆和做了一些研究可能的解決方案:

我找到一個方式來處理這個問題是使用WeakReference的,充滿細節上擺動的辦法聽衆可以發現here

然後我開始好奇的NetBeans表格編輯器是如何生成的代碼進行清理後,聽衆添加到窗體,發現NetBeans的是通過包裝對象登記聽衆即

argTypeComboBox.addItemListener(new java.awt.event.ItemListener() { 
    public void itemStateChanged(java.awt.event.ItemEvent evt) { 
     argTypeComboBoxItemStateChanged(evt); 
    } 
}); 

但是生成的代碼做通過撥打removeItemListener似乎不會清理。

問題

是包裝對象像個弱引用?對我來說,它看起來可能會泄漏少量的內存(包裝對象的大小)?

在處理聽衆時,您是否有其他方法來確保他們在完成垃圾回收時始終都會收集垃圾?

回答

14

首先是一個修正,這裏的潛在泄漏不是很小。一個匿名的內部類擁有對外部類的引用,所以只要監聽器可以訪問,它就會保持整個類。

但是,這通常不是問題,因爲您要將偵聽器添加到幀上的對象。當這個框架被丟棄(儘管重要),並且沒有更多的引用(這是非常典型的),它的所有組件都變得無法訪問(如果你沒有做任何事情),整個事情都會被垃圾收集。

但是,我曾經處理過一個應用程序,但它並沒有花哨的東西,比如用另一個窗口註冊打開的窗口,所以如果窗口關閉,它仍然被註冊 - 大時間內存泄露 - 這些窗口不是小。

所以底線是,NetBeans沒有做任何事情導致內存「泄漏」,因爲組件被框架引用而不在框外,組件引用匿名類,而匿名類又引用框架 - 處理框架和整個圖形是無法訪問的,但你必須小心聽衆,因爲他們可以這樣做給你。

+0

很好的解釋Yishai,你在處理那些花費大量時間內存泄漏的奇特應用程序中的偵聽器時採取了什麼方法? – Clinton 2009-12-10 01:56:19

+0

@Clinton,一旦我診斷出這個問題(這花了一段時間,很多分析),我只是一定要在窗口配置上註銷聽衆。我不記得所有的細節,但那是關鍵 - 我不知道弱引用是問題的標準解決方案,我可能已經能夠使用它。 – Yishai 2009-12-10 02:09:58

+0

@義海當聽衆離開示波器時,我一直在註銷,但它似乎有點笨重,並尋找更好的解決方案。再次感謝修正。 – Clinton 2009-12-10 02:21:25