程式者的胡言亂語
深入敵營的Java Part I
深入敵營的Java
今年我在JavaTwo 2006的講題是「IKVM.NET-深入敵營的Java」。看到「敵營」這兩個字,相信絕大多數人馬上就會聯想到.NET。沒有錯,它指的的確就是.NET。雖然身為Java開發者的我們(其實我同樣也是許多其他程式語言的開發者,包括.NET),毋需抱持什麼基本教義派的想法(程式語言是拿來用的,不是拿來拜的)將.NET陣營視為水火不容的對象,但就戰略上來說,.NET無庸置疑的,絕對是Java的「敵營」。不僅.NET整體概念仿效Java平台而來,C#更吸取Java程式語言的經驗,不僅本身與Java十分相似,更提出了許多增進之處。不論是.NET vs. Java或C# vs. Java,皆構成敵對的陣勢。雖然.NET本身就允許多種程式語言,但偏偏就少了Java。而這個講題,卻將焦點放在一個「特殊化」的JVM,也就是IKVM.NET。為什麼我將IKVM.NET稱為一個「特殊化」的JVM,我在稍後會解釋。
首先,讓我們來看看一段”Java”程式碼:
try { FileReader fr = new FileReader("log.txt"); BufferedReader br = new BufferedReader(fr); br.readLine(); br.close(); fr.close(); } catch(IOException e) { e.printStackTrace(); } |
熟悉Java的人,相信都能一眼認出這是一段Java的程式碼,但我們再接下去看:
using System; using java.io; namespace JavaCode { class Class1 { [STAThread] static void { try { FileReader fr = new FileReader("log.txt"); BufferedReader br = new BufferedReader(fr); br.readLine(); br.close(); fr.close(); } catch(IOException e) { e.printStackTrace(); } } } } |
但,它也可以是一段C#的程式碼。
在Java眾多的口號中,我記得有一個是「一次編寫,隨處運行(Write once, run everywhere.)」,這突顯了Java的無處不在。但我必須說,有了IKVM.NET,這句話大可修改成「一次編寫,隨處運行,包括.NET!」
什麼是IKVM.NET呢?簡單來說,IKVM.NET是可執行於.Net平台的Java實作,它是個JVM。在寫這篇文章之前,我想到,英文字母I與K的中間,不正恰好就是J嗎?作者取這個名字或許正有JVM.NET的相關聯想吧。許多人想到.NET,往往只會想到微軟的.Net Framework,殊不知有一個叫做「Mono」的開放原始碼專案,也是個努力與.NET規範相容的.NET平台。Mono可執行於Linux與Windows之上。而IKVM.NET的目標大致可區分為二:(1)在.NET上直接執行既有的Java應用程式(2)提供Java與.NET之間的interoperability。
IKVM.NET的系統架構
我們可以試著從兩個系統架構的觀點來看待IKVM.NET,一個是「JVM觀點」,而另一個則是「轉換器觀點」。下圖即為用JVM觀點來看待IKVM.NET的系統架構。

從JVM觀點來看到IKVM.NET,它就是一個疊在另一個VM上的VM,也就是疊在.NET之上的JVM,而且可運作於Windows或Linux平台之上。而對於Java應用程式而言,完全感受不到自己所存活的空間,其底層竟然是以.NET為基底的。由於IKVM是執行在.NET上的JVM,所以JVM本身能執行於所有部署.NET平台的環境之上。因此,有了IKVM.NET的加持,Java的確可以說是「「一次編寫,隨處運行,包括.NET!」。但這是邏輯上的架構,倘若直接利用.NET打造一個完全的JVM的話,那麼由於疊了兩層的VM,效能恐怕更打折扣。而這也不是IKVM.NET實際上採用的方式。我們可以用第二種觀點來看IKVM.NET的架構。
這個觀點就是轉換器的觀點。無論是稍後會提到的動態模式或靜態模式,IKVM.NET最主要的作用,還是將Java類別轉換成為.NET類別,搭配「可於.NET平台上執行的」Java程式庫,便可以借力使力的直接執行於.NET之上。許多Java與.NET在抽象上共通的機制,就由.NET一肩扛起,這大幅的簡化了IKVM.NET開發上所需花費的時間與力氣,也降低其複雜度。更重要的是,這樣子的做法,會為Java與.NET的互通,搭起一座不可思議的橋樑。
所以本文至此,可以重新再解釋何謂IKVM.NET:
l IKVM.NET是個「特殊化」的JVM,其特殊之處在於,它是一個執行於另一個VM上的JVM,更特別的是,這個VM還是它戰略上的競爭對手.NET。
l IKVM.NET提供了類別轉換器,可以在byte code層次進行Java byte code與.NET CIL之間的轉換。
l IKVM.NET內含Java core library的.NET實作,這使得被轉換至.NET形式的Java類別,在使用標準的Java程式庫時,不致於發生困難。而這其實是相當關鍵的一件事,因為儘管IKVM.NET有能力將Java類別轉換成為.NET類別,但倘若缺乏Java程式庫中的類別,這些Java類別則將失去依靠,也完全不能作用。而IKVM.NET所採用的Java core library.NET實作,來自於一個命名為「GNU Classpath」的專案,它本身並不是IKVM.NET的一部份,同時被許多FREE JVM的專案所採用,包括我們時常聽到的Kaffe以及gcj。
IKVM.NET所提供的,乃是一份編譯好的GNU Classpath在.NET上的版本再加上IKVM.NET額外的程式碼,也就是以.NET完成GNU Classpath所需的原生碼。有了GNU Classpath後,我們等於有了Java core library在.NET上的實作。
如上圖所示,IKVM.NET所提供的GNU Classpath實作,其檔名為IKVM.GNU.Classpath.DLL,當我們將它加入到Visual Studio .Net專案的reference,再透過Object Browser去檢視時,我們會發現,幾乎所有我們所熟悉的Java類別,都可以在這個DLL中找到,這…這可是.NET啊。沒錯,相信你的眼睛,這無疑的是一組Java核心程式庫在.NET上的實作-GNU Classpath的貢獻。
IKVM.NET的應用方式及利基
人們會想怎麼應用IKVM.NET呢?雖然想像是沒有邊際的,但是實務上應用IKVM.NET的方式主要還是三種:
l 動態模式:在這個模式下,我們把IKVM.NET當做是純粹的JVM,利用它直接在.NET上執行既有的Java應用程式(也就是.jar或是.class)。
l 靜態模式:IKVM.NET提供工具,讓你得以將既有的Java應用程式,利用離線的方式,轉換成為.NET上的執行檔或程式庫。這意謂著,你可以直接將.jar或.class轉換成為.exe或.dll。
l Java.NET:搭配動態模式,利用現成的Java編譯器,我們可以一開始就打定主意,用Java來開發.NET上的應用程式。
透過上述的應用程式,IKVM.NET提供了許多應用上的利基。首先,.NET上目前可以執行許多程式語言,甚至有與Java十分相似的C#及Visual J#,但有了IKVM.NET,我們就可以利用Java來開發.NET上的應用程式。再來,由於.NET平台到目前為止始終維持著與Java平台對抗的態勢,這使得某些微軟所主導的環境中,可能只存在.NET但卻缺乏Java。而有了IKVM.NET,Java便能借力使力,使得四海之內皆Java,即便在只有.NET的平台上,都能夠執行Java。.NET的擴張,不僅不會阻礙Java的散佈,同時還能有所助益。
我們可以來看看IKVM.NET應用上究竟有何神奇之處。我在JavaTwo 2004曾經介紹過一個開放原始碼的Java全文搜尋引擎Lucene。由於其效率佳,架構十分具備彈性,兼之以開放的特性,有許多使用.NET的開發者,建立了好幾個專案,全力促生.NET平台上的Lucene,包括了:NLucene、Lucene.NET、SearchBlackBox,以及dotLucene。其中,SearchBlackBox更是衍生自Lucene.NET的商業化版本。許多開發者對其商業化的態度以及商業化後撤除原網站上原始碼的作法不滿,更以Lucene.NET最後的開始版本為基礎,另起爐灶,成立了dotLucene專案,與其互別苗頭。
.NET世界裡花費極多心力,吵的不可開支。史蒂芬周可能會想說一句:「爭什麼爭,摻在一起做瀨尿牛丸啊」,呃,不是。是「乾脆在.NET上跑Java不就成了。」先來看看我的示範環境:
其中包括了執行IKVM.NET所需的runtime libraries,以及原始的兩個.jar檔。最後我們看到lucene.dll,以及SearchFiles.exe。其中lucene.dll便是我們利用IKVM.NET將lucene-core-
Posted at 10:43下午 八月 10, 2006 by Chien-Hsing Wang in Java |
星期四 八月 10, 2006
