TAG | swing
上次寫完 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.Frame 和 java.awt.Window 。本質上它們依然是一個 AWT 元件,只係在其上再加建 Swing 的 API 去支持運作。它們,依然是擁有 finalize method 的重元件(須要兩次 GC 才能清理)。
也就是你在自己 extends 了它們的 object 都自動成了重元件,令到任何在其中的 members 都無可避免地減低 GC 效率和增加記憶體使用量。而且,這根本就會令到你的物件本身的可重用性減低。
但很可惜在官方的 Tutorial Using Top-Level Containers 沒有提到這一點和它的重要性。
比較合理的做法是以 javax.swing.JComponent 或 javax.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 的設定。
Mr./Ms. Days (MMDays) – 網路, 資訊, 觀察, 生活 » Blog Archive » [MMDays 專欄] 版本控制,版本升級是不是個問題?
Posted by Mr. Saturday
Mr. Friday 的 Java會步上 COBOL 的後塵嗎? 一文還真是引起了相當多的討論,連在 FunP 上面都有一些高手們長篇大論的回應,另外我也看到了 qing 前輩也寫了篇文章 (剛剛也看到他來留言了) 來參與討論,Friday 也針對一些問題跟我私底下聊了一下.正好我自己也有一些淺薄的經驗,這邊就斗膽拿出來跟大家分享一下.不過我先開門見山地表明自己的觀點好了,基本上我覺 得拿兩個程式語言來比較好壞,就跟拿英文和中文來比較好壞一樣,意義不大.每種語言有他存在的目的和當初被創造的理由,也各有其優缺點,而且語言會因為使 用者而呈現出不同的面貌,真實生活中的語言如此,程式語言自然也不例外.
我比較想要談的,是像 Java 語言版本升級的問題,這也是 qing 前輩著墨甚多的一個問題,底下引述一段:
你沒有必要苦苦追趕Third party程式庫的新版本。通常,在產品開發之前,你就會決定你的技術解決方案,確定你所用的程式庫可以滿足你的需求。在產品開發中途決定更換所用程式庫的major version或到minor version是滿嚴重的事。大多數會需要選定新版的程式庫,多半是發生在選定開發一個新產品的時候。這麼一來,又怎麼會有「程式老跳訊息告訴你這個jar檔版本太舊不是他要的」的問題呢?
對於版本升級這個問題,我認為這絕對是個對工程師影響重大的事情.這邊我想舉出一個另外的例子和切入點,大家就會知道為什麼版本控制和升級會是個大問題.
大家的討論通常會把程式語言聚焦在產品上面.在單純地開發一個產品這方面,可能就像 qing 所講的,你一開始可以選定技術方案,確定所用的程式庫,中途不要亂更換版本,就不會有什麼問題,不過多數的時候在實際上,世界並沒有這麼美好.程式語言的 升級有的時候不只是更改語法或是加入新的 language feature 和 library,很多時候伴隨著升級而來的,是去除舊版本的 bug 和替換舊的 library,甚至於改變某些 function 的行為.這並不是你是否要當一個新版魔人的問題,當 你發現舊版本的 bug 可能會引響你的產品,甚至於你原本用的 function 被 deprecated 掉的時候,你必須去考慮升級,確保日後的相容性和穩定性.即使這件事情是發生在你的開發過程中,你也必須花費心力去評估或做修正,這當然是個大問題.不過 當然,如果你開發的產品是如此地完美,以致於以後所有的版本更新都不會影響到你,那麼以上我說的對你來說就不成立.但我相信大多數的人不是如此.
以上的討論只放在用程式語言開發一個一個獨立的產品上面,各位是否想過,當一個語言成為你全公司的 infrastructure 的時候, 狀況又會是怎麼樣?小弟任職的軟體公司,很不幸地就以 Java 去打造至關重要的 infrastructure.也就是說現在我們公司的工程師不只是用原生的 Java 去開發一個一個的產品而已,Java 這個語言本身已經擴展到全公司,成為很多環境的基礎,包括 parallel programming 的 framework 如 MapReduce;Remote Procedure Call 的 framework 等等,都是 based on Java 打造出來.這種規模和等級已經不是單一產品的問題,而是牽涉到以後所有還沒出現的產品和既有的產品,和全公司上千甚至上萬名工程師每天如何去寫程式的問題.
也因此,小弟公司內部有一個 team 叫做 Java Infrastructure Team,每次 Java 預定要推出升級的版本時,他們就如臨大敵,工作量暴增,必須立刻評估新版本對於全公司的影響,立刻做出反應,這牽涉到的問題多如牛毛,在管理上:有沒有必 要升級是一個問題;什麼時候升級是一個問題;其餘合作廠商是否升級也是一個問題;在技術上:新版本的 performance 是否有差異是一個問題;新版本是否又會帶來新的 bug 是一個問題;對於既有產品的影響又是一個問題;在人員教育上:升級之後的磨合期也是一個問題.請注意,我不是在談單一個人去開發單一產品,我是在說版本升 級 (即使是一點點最細微的更動) 如何同時影響到數千個產品,數千位工程師.在這種規模之下,很不幸地,你必須去苦苦追趕程式語言的升級.我想這也是為什麼 Mr. Friday 會提出版本升級的問題.
也因此,我認為版本升級,當然是個非常重大的議題.
—————————-
這也是我個人不喜愛 SWING 的原因,SWING 在不同版本之間的行為方式差異很大。重點不是畫面!而是操作的方式,一個簡單的 double click, select, highlight, 中文輸入, File Dialog, default look and feel…..等等,完全都不在控制之中。Sun 官方好像沒有想過每次都沒有想過每次亂來都會影響到多少人。
