Archive for the ‘Java’ Category.

網摘: Immutability in Java

很久沒 quote Java 的東東了

Part 1 on Immutability in Java:
http://jeremymanson.blogspot.com/2008/04/immutability-in-java.html

Part 2 on Immutability in Java:
http://jeremymanson.blogspot.com/2008/07/immutability-in-java-part-2.html

Part 3 on Immutability in Java - Deserialization and Reflection:
http://jeremymanson.blogspot.com/2008/07/immutability-in-java-part-3.html

 

 

重點是, final 是必需的。之前的 Javaspeciallist 的文章有有提到。final 的功用不但會限制寫入和方便 inner class 存取而已,它會影響 Just-In-Time compiler 的行為,和防止它作出過份優化而引起的錯誤。

該記著,JRE 不是一行一行執行你的 code(那只會在 debugger發生),而且在 JIT 在 SMP 的情況下會令到 bytecode 執行次序更加難以估計。該加上 final / violate 地方不要偷懶。

網摘: Scaling Your Java EE Applications

Scaling Your Java EE Applications

Scaling Your Java EE Applications Part 2

 


SMP 和 Server Load balancing 要注意的地方

最近好像和新的 Java 技術脫節了

最近推出的 Framework, library 的新版本,雖然知道,看到新聞,也讀過簡介,也參考過 sample code。

可是就沒有真正拿上手試過,寫過,用過。

總有一種,殺雞焉用牛刀的感覺而沒有在 small application 中使用它們。大型 application 的也很少要重新開發修改其 framework。

也會開始問理性地自己,為何要用新版?和舊版比較有甚麼特點?想過,仔細選擇過才去做。

 

難度我開始老了嗎。。。。。

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 的設定。

知得越多,就發現自己懂得越少

無論是 Java,英文,朋友,人際關係甚至係金錢管理。

古人話:『苦海無邊‥』呀唔係『學海無崖,唯勤是岸』都沒有錯

無論是甚麼人,學習甚麼也好,每學一件事,就會生出更多的問題要去解答,去再學習。不是你覺得已經足夠而放棄了學習,就是持續一直學下去,而永遠沒有學完了而停止的。

勤力的人,會比較快學得到他所需要的足夠的知識。但如果他停了下來放棄了 勤,就會慢慢被無情的浪再卷入學海當中。

 

最近,學習的進度好像學了下來。發覺自己雖然經學了不少,卻好像看到很多的地方要去學習改善。

我很疲倦而停下了腳步,我根本不能集中精神去學習。我心思都被某個人填滿--看吧,我原本沒有打算寫到她的,但還是這樣。

Java, Garbage Collection與 Memory management

很多新手都以為, Java 和相比 C++,JVM 內置了 Garbage Collection 的功能就相等於 "我不用管" / "我可以寫少幾行 code",這種想法,是要不得的。

其實這也難怪,太多書本和教學寫得都不清楚,甚至錯誤百出。
不是為了吸引新手使用 Java,就是把它定義為進階深入的知識,或根本連作者本身都錯誤理解了。

其實無論是 Java , .NET 或其他附有 GC 或其他聲稱有 GC 功能的語言,也要自己面對資源回收的理

為垃圾而設想

Garbage Collection (垃圾回收) 能有效率地運作的大前提是,它要知道甚麼是垃圾,甚麼不垃圾。
理所當然的,當你手上還捉緊著它們,還有 Object 之間千絲萬縷的連結,你又叫 GC Engine 如何替你進行回收呢?

其他的還有 GC 的時機,策略,優化(避免劣化) 也是要由寫程式的人來想。

別忘了它們的手足

GC 本來就只能替你回收記憶體,可是你不要忘了除了記憶體,你還有別的垃圾。IO Handle, native code 的 pointer 或其他向 OS / Hardware 要來的資源 。GC Engine 是不知道如何釋放/回收它們的,GC 能做到的只是告訴你:『我看到它上面有條便條,它要我在回收之前通知你,記得有其他的事情要做』---也就是 finalize method。

當 GC engine 看到將要回收的 Object 上有 finalize method,則會把它們放到一邊,經由獨立的 Finalizer Thread 執行。而你要做的,就是記得在 finalize 內把自己用到的 sub-process / native pointer / windows handle / file handle 經由 JNI 方法自己放掉。正如在 C 當中 delete pointer 之前要把子內容清掉一樣。

可幸地, JDK 內所有一般性會使用 native resource 的 Object 都已實作了 finalize,你在正常情況下都不必為它們底層的 File Handle, Socket, GUI Handle, pointer…. 等等太過粗心。不過你還是要注意和小心的!

你應該知道 SWT / Swing 和 AWT 吧!我以前讀 SWT 介紹的時候都不了解這一小句『SWT doesn’t  use the Java garbage collector….』當時我看不懂,近年才有所覺悟。它所說的,不是指 Java 中Object 記憶體的回收,而是指不等待不使用 GC 的 Finallizer 來回收 GUI Handler。 先說一點歷史,當年 AWT 設計上最失敗的地方不是其 heavy-weight (這只是 Sun 用來騙人的術語),也不是 GUI 的 cross-platform 問題。而是其而是其設計高估 GC 的能力 Finalizer Thread 的速度。 finalize 最大的多點是所有實現了它的 object 和它的子部件都至才要經過兩次 GC 才能被清掉,基本上所有使用了 AWT 的 Java Process 的 GC 都被劣化(使用 AWT 的大前提是你不應 extends 任何 AWT 元件)。而且 OS 能用的 GUI handle 數目是有限的,可是 AWT 就喜歡拿了一堆 Handle 不放手(還沒有 finalize 掉),令到整個 OS out-of-resource 的機會大大提高。
Swing 就是應用了 light-weight (另一個騙人的術語) 的想法,減少向 OS 要求 resource,把 GUI 放入自己管理的部份。SWING 自行產生,管理,繪畫,事件,消除。(怎麼看都是把原本 OS 做的事搶來自己做,根本是更加重,更加 heavy-weight 才對) 來達到多重目的。 LookAndFeel 是其中最沒有用最浪費,郤又最多人掛在口邊的的。

而 SWT 的想法就是:『好吧,我知道它們是何時成為垃圾,就由我來把它回收吧。』
很簡單,很易了解,其實也只是要求 Progarmmer 去做他們本來就應該要做的工作。

GC 不只是 Garbage Collection

上文不是提到 GC 是回收記憶體中的垃圾和其他垃圾嗎?為甚麼又說它不是垃圾回收呢?

的確,原本的 GC 的用意 (包括 Java / .NET / C++ 和其他) 很可能根本只是垃圾回收。可是把它套用在近代的 JVM 上就有點太過小看 GC 了。GC 的另一樣重要的價值是自動化的記憶體管理。簡單來說,就是能否善用空間的能力。

記憶體管理大概可以被分為:配置,釋放,重置,定位等等。

根據支持者的研究文件指出(忘了出處),老舊的 C/C++ 當中的 配置/釋放記憶體雖然每次都很快,但卻是 stop-the-world 的動作,效能算起來會和有 overhead 的 Java 差不多,甚至比 Java 差。

另外 GC 能避免 memory fragment 。fragment 的出現是因為程式每次向OS 要求 memory 都是以 page 為單位的,反復的配置/釋放會減低 page 真正需要使用的密度。JVM GC 在執行的時候,很多時候也會把 Object 的本體移來移去(e.g. Generational GC)。也是能把 2/5 + 2/5 + 1/5 整合為一個 5/5 的時機。VM 理論上和部份的實作上是做得到把常用的,連著使用的 object 放在一起,而把不太相關的,很有機會被垃圾掉了又放在另一個 page 內,而直接減少底層執行指令的負擔。例是說 String 本身和內在的 char[] 經常放在一起,減少要在多個不同的 page 讀寫的機會。

GC 它能做到的,它替你做到的,都比你想的多;但你也需要寫 GC friendly 的程式才行。

網摘: Lucene 2.3:大幅提升索引性能,新增機器學習項目

InfoQ: Lucene 2.3:大幅提升索引性能,新增機器學習項目

Ingersoll認為這次的版本中最大的變化是新的索引算法,它使用了新的in-memory模型來達到大幅的速度提升。據Ingersoll 說,單單是把Lucene 2.2 JAR換成Lucene 2.3 JAR就能在某些測試中把索引性能提速500%。其他改變還包括:

  • 改進的索引管理——以前在索引過程中,當合併內部索引文件時偶爾會出現長時間的停頓,現在已經消滅了這種現象。另外現在也更容易實現其他途徑去管理索引過程。
  • 對象池——DocumentFieldToken的實例現在可在索引分析中重用,因此不但提升了分析的速度,還減少了索引過程中的內存分配次數。
  • 重新打開IndexReader ——重新打開一個IndexReader去捕捉索引中最新的變化,這個操作的速度現在也更快了,新的reopen()方法只會加載那些變更過的索引片斷,而不是重新加載完整的索引。
  • 更簡易的IndexWriter微調——setMaxBufferedDocs已被更直觀的setRAMBufferSizeMB所取代。

另外,2.3的目標是只需通過文件替換就能換下2.2,完全不需要重新編譯。這裡是完整的更新說明