Adv

4/16/2008

Finalize 和 JWindow, JFrame, JDialog

上次寫完 Java, Garbage Collection與 Memory management 當中提到 AWT 和 Finalize 的關係,仔細一想後覺得大有文章,要再寫多少少。


 


有一少部新手入門看的書當中介紹的做法,和一部份 WYSIWYG GUI Editor 的做法,都是以 JDialog / JWindow 來實作自己的的視窗。可是根據 Swing 正確的 MVC design pattern 和 finalize 的關係來說,這是完全錯誤,而且可笑的,荒謬的做法。
如果只是為了即省幾行 code 或即省介紹每一節的功能,那就比較合理,但卻會教壞新手。


 


javax.swing.JDialog, javax.swing.JFrame javax.swing.JWindow 都是 extends 了 java.awt.Dialog, java.awt.Framejava.awt.Window 。本質上它們依然是一個 AWT 元件,只係在其上再加建 Swing 的 API 去支持運作。它們,依然是擁有 finalize method 的重元件(須要兩次 GC 才能清理)。


也就是你在自己 extends 了它們的 object 都自動成了重元件,令到任何在其中的 members 都無可避免地減低 GC 效率和增加記憶體使用量。而且,這根本就會令到你的物件本身的可重用性減低。


但很可惜在官方的 Tutorial Using Top-Level Containers 沒有提到這一點和它的重要性。


比較合理的做法是以 javax.swing.JComponentjavax.swing.JPanel 為基礎,而另外自行寫一組簡單的 function 來實現



frame=new JFrame();
frame.getContentPane().add(xxx);



而且,也為了 GC 優化,在確定 Window 不會重用(不會再執行 show() 或 setVisible(true);) 的地方(例如 void windowClosed(){...} ) 加上



frame.getContentPane().remove(xxx);
// 別忘了還有 Menu 和其他



,令它們和重元件 window 分離。


這樣一來,在 GC 的時候,它就能把 Windows 和 載有大量 data 的部份分開辦理,在 JPanel 當中存在/連結的大量 memory 能一口氣在第一次 GC 就能被清掉,而不是等 finalize 執行後的第二次 (甚至第三次, 第四次) 的 GC 才能被移除。


當然這樣的 GC 優化這對只會冇單一 Window 的 application 沒有特別意義的,也對 EXIT_ON_CLOSE 的 window 沒有意義。但能算是比較正規的做法。


 


 


我不喜歡 Swing,它實在太易令人犯錯而不自知。特別是那不 Thread-safe,但又難以 debug 的設定。

沒有留言: