9

我在我們的應用程序中發現的一個內存泄漏是java.awt.Window.allWindows私有靜態字段,它跟蹤實例化的每個窗口。我們有創建,使用和遺忘的對話框,期望這些對話框會消失並被垃圾收集。這個私人領域將無限期地保持在範圍內,直到他們調用dispose()方法。而根據定義,當他們超出範圍時,我們不能這樣做。爲什麼你必須處理()一個java.awt.Window超出範圍?

我不明白爲什麼這是這樣設計的。這似乎違背了垃圾回收的精神,當我完成一個Window對象時,必須明確讓系統知道。很明顯,我已經完成了它,因爲它超出了範圍。

我明白dispose()方法在做什麼:擺脫系統對等對象。我明白,這是在Java之外,你需要一些方法來做到這一點,Swing不應該失去對這些對象的追蹤,否則它會有內存泄漏。但是,當我永遠不會再使用它時,通過永久保留對我的Window的引用可以實現什麼?

有人可以解釋爲什麼這是必要的嗎?

+0

當調用removeNotify時,窗口將從allWindows中移除。 '窗口'包含本地資源,因此應該像處理數據庫連接一樣以相同的方式處理。 – 2009-09-11 00:53:05

+0

我的印象是,當我的數據庫連接超出範圍時,它們會自動關閉。我可能是錯的。 :)但現在,除了短程序之外,所有這些都是由服務器管理的。 – skiphoppy 2009-09-11 20:07:51

回答

14

我討厭這麼說,但這只是GUI的工作原理。

Windows是非阻塞的。這意味着一旦你在代碼中創建一個代碼,你的代碼就會繼續執行。

這意味着您的窗口可能在創建之後立即超出範圍,除非您明確地在其他地方存儲了引用。此時窗口仍在屏幕上。

這也意味着當你完成它時你需要一些其他方式來擺脫它。輸入Window dispose()方法,該方法可以從Window的一個偵聽器中調用。

+1

D'oh!我知道了!人們一直創建窗戶,他們不保持引用,但窗戶仍然可見並正在運行。我只是沒有想到這一點,因爲在這種情況下,我們立即使用窗口,然後使其不可見,然後忘記它(超出範圍)。現在我明白爲什麼這是Windows的默認設置。我知道在某個地方有一個合理的用例。 :) – skiphoppy 2009-09-10 19:56:46

+0

哦,對,我應該指出,當它的變量超出範圍時,窗口仍然在屏幕上。我會將其編輯到我的回答中,以防有人錯過。 – Powerlord 2009-09-10 20:14:06

2

這也許可以解釋它:AWT Threading Issues

簡單地說,有很多更在JVM不僅僅是有形成分在進行中,後臺線程等等。這些線程和其他資源一直保留到JVM上的最後一個窗口被處理完畢,然後整理完成,然後JVM可以乾淨地退出。因此,您使用的每個窗口,框架和對話窗口基本上都會鎖定JVM以防止它退出,並且您必須通過調用dispose()來手動管理此窗口。

我同意這是一個雞毛。我自己已經碰到過幾次了。

1

在Java中,當您有本機代碼(這是這些Windows組件的同級)時,您需要保留一個引用,以防止垃圾收集器嘗試垃圾收集對象,而本機指針仍在,這會導致各種不好的東西(VM崩潰等)。

例如參見here

1

dispose()方法破壞了WindowEvent對象所持有的對象。它不會終止應用程序/ p