編者註:本文介紹的內容主要是基於Fedora4版本,儘管現在Fedora已經發布了8版本,但經過內部討論我們還是決定發布這篇文章,原因在於本文提供了一個很好的開發思路,相信對讀者會有幫助!
在Fedora的發布版中,Fedora4是首個包含了大量用Java編程語言編寫的代碼的版本。正是由於GNU類路徑(Classpath)和GNU gcj(GNU Compiler for Java)的改進才促成了這些附加部分。
首先,GNU gcj不是Java。
然而,gcj的目標是實現一個完整的系統,該系統兼容於Java並且將預編譯器(ahead-of-time compiler)置於中心。它擁有一個基於GNU類路徑的凈化類庫和一個內置的解釋器。其編譯器可以將Java源文件、類文件、甚至是整個jar文件編譯成目標碼。
以前gcj對待Java採取的是一種“激進且傳統”的方式,它認為Java好像是C++的某個不常用的方言似的。這麼做有好的一面,然而不幸的是兩者的運行時鏈接模型差異太大——因此當遇到一些規模比較大、複雜度比較高的Java應用時,這種方法就無能為力了,特別是面對那些有著複雜的類載入機制的Java應用時,顯得尤為突出。
在GCC4.0的發布版中,我們對gcj實現了一種新的編譯方式,稱之為二進位兼容性ABI(Binary Compatibility Application Binary Interface)。這種編譯方式將所有的鏈接推遲到運行時刻進行並且完全實現了Java的二進位兼容規範——正好是讓預編譯的代碼與類裝載結合所需要的。
我們還增加了一個類映射資料庫。在運行時,只要我們定義好一個類,gcj運行時(叫做“libgcj”)就會在資料庫中尋找這個類。如果找到該類(注意我們這裡使用的是類的“內容”,而不僅僅是類名),那麼libgcj就會映射到該共享庫中,該庫包含了編譯后的類。
這兩個改變使得我們可以做一些更強大的事情:我們可以預編譯Java程序而不必要求任何應用級的改變。此外,由於採用了新的方式對位元組碼進行校驗,我們還能確保編譯的代碼在運行時的類型安全。
在Fedora Core上構建Java應用是很簡單的——現存的構建方式不會發生變化。Fedora Core舶來了“Ant“並且使用來自Eclipse的Java編譯器將Java代碼編譯成位元組碼。
描述如何編寫RPM已經超出了本文討論的範圍,但是Fedora RPM指南上有一些有用的信息,JPackage上也有一些Java特定的指南。
一旦你的程序被編譯成位元組碼,你就可以將他們編譯為本地代碼。因為gcj尚不包含一個即時編譯器(JIT),這就是其獲得合理性能的方法。在某些情況下,其性能可能會超過已有即時編譯器,因為gcj使用了共享庫……當你同時運行應用程序的多個實例時,你就會看到這種巨大的差異。
Fedora提供了兩個程序,使得本地編譯包的工作變得更簡單。我們在構建RPM時會使用到他們。
第一個程序是“aot-compile-rpm”。它會搜索jar文件並且使用gcj將他們編譯到共享庫中。aot-compile-rpm知道一些gcj特定的技巧,例如在編譯前將比較大的jar文件分割為若干個小的文件(在運行時編譯一個大的jar文件將耗費大量內存資源),在鏈接結果共享庫時使用–Bsymbolic(這會導致運行時性能改善)。
假如你沒有在構建RPM,那麼一個替代方案就是直接將程序中的jar文件編譯到共享庫中。這裡我展示一個最簡單的方法(我之前提到過,對於一個大的jar文件,這樣做會非常慢):
gcj -fjni -findirect-dispatch -fPIC -shared \
-Wl,-Bsymbolic -o foo.jar.so
foo.jar
分解一下:
Fedora Core提供的第二個有用的程序是rebuild-gcj-db。當安裝或者卸載一個RPM改變了全局類映射資料庫時,我們將使用該程序,並且該程序應該運行在RPM的%post和%postun部分。
rebuild-gcj-db根據約定來運轉——它假設每個包在目錄/usr/lib/gcj(對於多架構操作系統中64位的包,目錄為/usr/lib64/gcj,有相應的RPM宏去解決這個問題)下的某個地方安裝自己的類映射資料庫。然後它循環遍歷所有的這些個體資料庫並且把他們整合到運行時使用的全局資料庫中。
注意到使用gcj去編譯一個Java程序並不總是能成功的。Gcj的類庫尚不完整,有時程序會使用到某些尚未實現的API。例如,Swing目前仍在積極開發中。同樣,儘管Sun公司已經發布了警告,一些包使用了私有的com.sun.*或者sun.*下的APIs,——然而一般來說,gcj並沒有實現他們。
Fedora Core 4使用了gcj來為很多應用程序進行編譯。
JOnAS應用伺服器,一個J2EE實現,也在進行中但是它還尚未通過Fedora Extras的審查。
在過去的一年中,GNU Classpath社區向著目標大踏步地前進,我們期望在2006年能繼續保持這個勢頭。我們有一個經常更新的API比較頁面;你可以在這裡追蹤我們API的狀態。
我們也在為gcj的核心改進而努力工作著:將編譯器,運行時和類庫更新到Java5。
最後,我們正在libgcj里實現Java的安全架構。這會實現一個Mozilla的插件和netx(Java Web Start的一個實現)。
Tom Tromey於1990年畢業於加利福尼亞理工學院。現主要從事Red Hat下的GNU Java編譯器和運行時開發工作。他編寫了GNU Automake。
查看英文原文:Delivering Java Apps on Fedora Core
[火星人 ] 在Fedora Core上交付Java應用已經有431次圍觀