Java發展歷程
J2SE:懷胎
Java的歷史可以追溯到1991年4月,Sun公司的James Gosling領導的綠色計劃(Green Project)開始著力發展一種分散式系統結構,使其能夠在各種消費性電子產品上執行,他們使用了C/C++/Oak語言。由於多種原因,綠色計劃逐漸陷於停滯狀態。
直至 1994年下半年,由於Internet的迅猛發展和環球資訊網的快速增長,第一個全球資訊網路瀏覽器Mosaic誕生了;此時,工業界對適合在網路異構環境下使用的語言有一種非常急迫的需求;Games Gosling決定改變綠色計劃的發展方向,他們對Oak進行了小規模的改造,就這樣,Java在1995年的3月23日誕生了!Java的誕生標誌著網際網路時代的開始,它能夠被應用在全球資訊網路的平臺上編寫互動性及強的Applet程式,而1995年的Applet無疑能給人們無窮的視覺和腦力震盪。
但沒有相應的開發庫而只靠Java語言來進行開發肯定是困難重重,所以Sun公司在1996年的1月23日釋出了JDK 1.0來幫助開發人員的開發。JDK包括兩大部分:執行環境和開發工具。緊跟著,Sun公司在1997年2月18日釋出了JDK 1.1。JDK1.1相對於舊版本最大的改進,是推出了JIT(Just-In-Time)編譯器,另外一個改進是AWT 1.1。
在JDK 1.1時代,Java平臺分為PersonalJava與EmbeddedJava,前者比較適用於運算資源和記憶體豐富的裝置,而資源有限者適用於後者。這樣的分類明顯不符合時代發展的潮流,所以,Java平臺處處蘊藏著新的翻天覆地的革命……
J2SE1.2:誕生
JDK 1.2在1998年12月4日的隆重發布,標誌著Java2平臺的誕生。Java 2的J2SE 1.2時代是一個大變革時代,它進行了如下的三大革命:
● 市場推廣革命
Sun公司在Java 1.2版以後將JDK 1.2改名為J2SDK,將Java改名為Java 2。在1999年Sun公司還將Java 2平臺分為三大塊:J2SE,J2EE,J2ME。這次市場推廣革命順應了網路急速發展的潮流,對Java 2平臺的發展起到了很好的催化劑的作用。
● API供應標準革命
而隨著供應商的不同,Java的API分為三大類:
Java Core API:由Sun公司制定的基本的API,所有的Java平臺都應該提供。
Java Optional API:由Sun公司制定的擴充API,Java平臺可以有選擇地提供。
特殊API:由特殊廠商或者組織提供的API。
● API制定過程的革命
如果你有需求不能通過遵循標準的API來實現,可以向JCP提出制定新的API的請求,經過稽核,你的請求可能被通過或者駁回;如果是被通過,則開始進入制定該API的程式。
J2SE 1.2時代進行的這些革命形成的制度一直沿用到現在,對Java技術的發展形成了深遠的影響。
除了上述的三大革命,Java 2還支援並新增了許多新特性,最受追捧的當屬Swing庫。Swing是輕量級的API,它不但有各式各樣先進的元件,而且連元件風格都可抽換。Swing出現之後,大家很快地就不太使用AWT了。Java 2還廢棄了一些API,最重要的莫過於Thread類中對suspend(),resume()和stop()等方法的廢棄。由於JDK 1.1的集合類庫中的Vector類和HashTable類都考慮了同步,在平常的使用中影響效率,所以Java 2專門添加了對應的非同步類,並完善了集合類庫。
J2SE1.3:拓廣
Java 2平臺推出後,得到了市場的強烈反響,所以,在2000年5月8日推出的J2SE 1.3對J2SE 1.2的改進,主要是對各種已有API的加強和對新API的拓展。
數字運算:加入了java.lang.StrictMath,方便我們的一般的數字運算。
新的Timer API:相信大家對其中的java.util.Timer和java.util.TimerTask一定不陌生。
Collections包:加入了一些新的API,方便我們的使用。
虛擬機器停止鉤子:J2SE 1.3還加入了一個強大的功能,那就是虛擬機器停止鉤子(Virtual Machine Shutdown Hooks),這個功能使得我們能夠在虛擬機器停止時完成我們自己的操作,比如關閉網路連線或者儲存會話狀態或者清除臨時檔案等等。
DNS服務:在JNDI介面方面,加入了一個DNS服務的實現。
Jini實現:J2SE 1.3包含了一個Jini實現,這使得我們可以方便地把諸如印表機、攝像機和磁碟驅動裝置插入現有網路中,並且能自動搜尋已在網上的裝置可以提供的服務並享用這些服務。
XML支援:由於計算機網路和XML技術的快速發展, J2SE 1.3在Optional API中引入了Java API for XML包。
HotSpot虛擬機器:J2SE 1.3引入了HotSpot虛擬機器。在Solaris版的JDK 1.3中,已經不支援傳統的虛擬機器,而Windows版的JDK 1.3同時支援傳統虛擬機器和HotSpot虛擬機器。
從上面的分析可以看出,J2SE 1.3主要是對J2SE 1.2查漏補缺和拓展新的API。從應用領域方面考慮,J2SE 1.3已經涵蓋了資料庫、WEB、多媒體、網路、電話、影像、加解密、圖形等等大部分的資訊科技領域。
在這個時期Java 2還有一個重要活動就是推出SCSL(Sun社群原始碼許可)許可協議。Sun公司開放原始碼專案的“女1號”Danese Cooper在1999年加入公司,負責Sun(包括Java)和開放原始碼社群之間的協調工作。Sun一直儘可能在贏利和開放原始碼之間尋求更好的平衡。
Java的大行其道引起了Microsoft的警惕並直接導致了.Net的產生,這同時也宣佈了Java作為獨一無二的Internet平臺地位的結束。這兩個對手在較量中相互學習,現在在技術架構上的目標上已趨相同。
J2SE 1.4:快速
J2SE 1.4平臺的推出發生在2002年2月13日,由於此前在Java平臺和.NET平臺間發生了規模浩大的孰優孰劣的論戰,而論戰中,Java平臺最大的缺點就是效能問題,所以J2SE 1.4平臺把效能的改善放在了最重要的位置。
HotSpot虛擬機器:HotSpot虛擬機器能夠很大程度上提高效能,所以J2SE 1.4已經不支援傳統的虛擬機器。現在,啟動應用程式應該通過-client或者-server選項來啟動。
鎖機制:由於舊版的HotSpot虛擬機器的鎖機制會導制嚴重的效能和功能問題,J2SE 1.4已經改寫了該鎖機制。
安全API:JCE、JSSE和JAAS這三大安全API從optional API移到了core API中。這樣,J2SE 1.4的安全域(SecureRandom)實現可以利用作業系統提供的安全機制,以便縮短應用程式的啟動時間。
RandomAccess標記介面:加入了RandomAccess標記介面,如果一個List實現了該介面,則表示它支援快速的隨機訪問,這樣可以提高List訪問的速度。
LinkedHashMap:加入了LinkedHashMap,這是一個插入排序的Map實現,但它的執行速度和HashMap一樣快。
反射:很多產品中都要使用反射(Reflection)機制,但大家知道,反射是相當耗時的,所以,J2SE 1.4中重寫了java.lang.reflect.Field、java.lang.reflect.Method.invoke()、java.lang.reflect.Constructor.newInstance()和Class.newInstance()等方法,使得我們利用反射也能寫出高效能的應用程式。
64位計算:J2SE 1.4支援64位計算。
新的I/O API:J2SE 1.4在API層面最大的變動,就是它更新了原有的java.io包,以及加入了一組更有效率更多功能的New I/O API。
斷言和日誌處理:J2SE 1.4版本在Java語言層面上加入了斷言(assert關鍵字),在API層面上加入日誌處理API,這些為程式的除錯提供了強有力的支援。
從上面的分析可以看出,Java 2平臺在經過數年的發展後,已經比較成熟穩定,J2SE 1.4主要是對平臺的效能進行較多的考慮和修改。在分散式程式方面,1.4版比1.3版的執行效率提高了一半以上;而在客戶端程式方面,1.4版比1.3版的效率提高了1/3。
J2SE 1.4版是J2SE第一個參與了 Java共同體過程(JCP)的J2SE版本。 像Borland、Compaq、Fujitsu、 SAS、 Symbian、 IBM這樣的公司,和Sun一起定義並發展了J2SE 1.4規範。在開放、良好的文件編撰與管理的過程中,形成了一個高質量的、代表了Java共同體的多樣性的規範。
J2SE5.0:易用
在2004年十月J2SE 5.0釋出的時候,Sun公司這樣解釋這次版本名稱不是J2SE 1.5而是J2SE 5.0的原因:“從Java誕生至今已有9年時間,而從有J2SE算起也有5個年頭了;在這樣的背境下,將該版本號從1.5改為5.0可以更好的反映出新版的J2SE的成熟度、穩定性、可伸縮性、安全性。”
J2SE的這次變更之重大和意義之深遠,的確也值得我們為之把版本號變換到J2SE 5.0。我們再看看Sun公司網站對J2SE 5.0的features描述:“通過增強Java平臺的力量,允許開發者更容易地使用,Java程式語言的這些改進將吸引大量各種Java開發者”,這是“Java技術發展歷程的一個重要里程碑” 。從這個描述我們可以看出,J2SE 5.0最大的目標是通過提供易用性而吸引各種開發者(當然包括以前的C/C++開發者) ,而它對以前版本的修改並不僅僅是API的升級,而且包括對Java語言層面的改進,被譽為是”自Java問世以來的最大一次語言標準變化”。
訪問環境變數:最初的Java語言有一個訪問環境變數的方法System.getenv(),但因為Java宣稱的”Write Once,Run AnyWhere”特性,所以在JDK 1.0中去掉了這個能夠訪問平臺專有資訊的方法。在J2SE 5.0中,它又來了,並有所擴充。由此可見J2SE 5.0對程式設計方便性的重視程度。
泛型:J2SE 5.0提供了強大的泛型機制,讓程式設計師可以減少程式碼重複,這個變化應該可以吸引小部分的C#開發人員吧。
增強的for迴圈:為了克服普通for迴圈的程式碼臃腫特點,J2SE 5.0提供了增強的for迴圈,我們現在可以這樣寫一個for迴圈:
public void printAll(Collection coll)
{
for(String str : coll)
{
System.out.println(str);
}
}
怎麼樣?是不是簡單了很多?
自動的裝箱/拆箱:
可變引數數目J2SE 5.0開始支援Varargs(不固定自變數個數),J2SE 5.0中還加入了以前拋棄的列舉和C風格的格式化輸出,這應該是為了吸引以前的C開發者吧。畢竟,在C開發中列舉和格式化輸出用的是太多了。
併發 J2SE 5.0中加入了java.util.concurrent包,並向集合框架中加入了Queue介面,J2SE 5.0還為各種集合提供了併發情況下的實現。
Properties類增強 由於XML的普及性應用,J2SE 5.0為java.util.Properties類加入了從XML檔案中裝載屬性和把屬性值儲存到XML檔案中的方法。
Annotation功能J2SE 5.0提供了註解(annotation)/元資料(metadata)功能,相信以後的大部分應用產品都將充分利用它的註解而實現產品的各種特性。
其它J2SE 5.0還在多執行緒(併發機制)、安全、國際化、UI等方面進行了大規模的變更,使得我們能夠更方便地進行Java開發。
其實,上面的這些變更,並不是我們程式設計師非要不可的內容。我們完全可以通過自己的辦法來達到這些變更實現的功能。但J2SE 5.0的目標就是讓我們程式設計師能夠更加方便地進行開發,所以,我們在基於J2SE 5.0開發時,應該能夠明顯的體會到它的易用性。
展望
時至今日,J2SE已經發展為一個覆蓋面廣、效率高、易用性強的技術平臺(見如下的J2SE API體系結構圖),但Java並沒有停止前進的腳步。Mustang版本的J2SE正在緊鑼密鼓的開發當中,按以前的慣例,每兩年會發佈一個全新的J2SE版本,所以Mustang開發版對應的J2SE 6.0釋出版將在2006年完成。
2005年5月23日是Java技術十週年慶典日,在這十年的發展中,Java平臺吸引了四百萬開發者,在網路計算遍及全球的今天,更是有17.5億臺裝置使用了Java技術。作為Java技術的基礎,J2SE的功績不可掩沒,我們期望J2SE伴隨Java平臺一路走好!
1995年3月23日,San Jose Mercury News登出一篇題為“Why Sun thinks Hot Java will give you a lift”的文章,在那篇文章裡預言Java技術將是下一個重大事件,這個預言現在看來並不僅僅是商家的宣傳伎倆,雖然文章是當時Sun的公關經理 Lisa Poulson安排撰寫的。從世人知道Java那一刻起到現在,算起來已經過去整整十年,回顧過去的十年值得總結的東西有許多,但在這裡筆者只想就Java 開發環境談些個人的想法與朋友們交流一下。
現在的軟體開發人員在整個軟體的開發生命週期裡,也許會根據需要使用各式各樣的開發工具來完成相對複雜的開發任務,而在幾十年以前,人們還只是使用文字編輯器、編譯器和Debugger進行開發,對於這個階段的開發環境人們稱之為CLEs(Command Line Environments)。 而當人們發現如果將那些單獨分開的開發工具整合起來就可以有效的提高開發效率時,IDEs(Integrated Development Environments)就出現了。Java的出現儘管只有十年,但其開發環境也大至經歷了從CLEs到IDEs再到XDEs這三個階段,現在即將進入CDEs階段。在上述Java開發環境發展過程中,有許多值得我們大家關注的地方。
Java開發環境的歷史回顧
縱觀過去十年Java開發環境的發展,大致可以粗略的劃分為如下幾個階段:
● 1995,命令列開發環境CLEs
● 1996-2000,整合開發環境IDEs
● 2001-2004,擴充套件開發環境XDEs
● 2005至今,協同開發環境CDEs
1995年,不平凡的一年,這一年Java 獲得了成功。可令人尷尬的是在1995年並沒有一個令人滿意的Java開發環境,開發人員在進行Java程式設計時,大多使用文字編輯器編輯源程式,然後再使用命令列的方式進行編譯處理。那時的Java開發環境還處於CLEs時代,開發效率非常低,這預示著在Java開發工具上會有一番激烈的競爭。
有人稱1996年為網際網路年,有人卻稱之為Java年,還有人稱之為Web開發年,但不論如何稱呼1996年,它都反映了一個事實:Bill Joy將Java與網際網路相結合的策略取得了成功。這一年的9月Sun推出了其Java開發環境-Java WorkShop,這是一款基於瀏覽器的Java開發工具,但由於當時 Java在許多方面還不成熟,所以實際上Java WorkShop並不成功,同年釋出的Symantec Visual Cafe由於還是採用C/C++語言進行開發,所以效能與成熟度上就比WorkShop好得多。提到Visual Cafe就不能不提Eugene Wang,因為Eugene Wang常常是與計算機間諜這個詞同時出現的人物,有人甚至講當時Symantec的老闆Gordon Eubanks與Eugene Wang簽約時,也同時簽下了監獄裡的一個單元。Visual Cafe就是由Eugene Wang進行主要策劃的,它是在同一年釋出的Java開發環境中,唯一解決了與資料庫連線問題的開發環境,帶有一套可以與資料庫相連線的元件,無需太多程式設計使用拖拽的方式就可完成大部分工作,這一優點使得Visual Cafe受到了Java開發人員的歡迎。這一年IBM收購了OTI公司,從而得到了Dave Thomas的弟子John Duimovich、Dave Thomson、Mike Wilson等一大批軟體精英,這之中還包括“生活在技術刀鋒上的開發者”Brian Barry。
1997年,由於微軟壟斷案,使得微軟在Java開發環境上的努力受到了限制,Visual Cafe由於介面直觀易用,可以很容易地連線各種資料來源等功能再次受到開發人員的歡迎。這一年IBM釋出VisualAge for Java。VisualAge for Java是面向程式碼庫的開發環境,它提供程式碼庫和專案管理以便於開發團隊在 C/S環境下進行專案開發。但由於大多數Java開發人員比較熟悉面向檔案的開發環境,還不太習慣面向程式碼庫的開發,再加上VisalAge for Java對系統資源的要求比較高等因素,使得VisualAge for Java一開始未被Java開發人員所認可。
1998年至2000年比較成功的Java開發環境是JBuilder,這是由於Borland較好的把握住 J2SE、J2EE和J2ME釋出後,Java技術升級的時機,全面支援Java1.1和Java1.2開發平臺,它還提供了多種工具方便使用者從舊的平臺遷移到新的Java平臺。JBuilder本身80%是基於JDK1.2進行開發的,它支援JavaBeans, Enterprise JavaBeans, JDBC等方面的應用開發,可以連線多種關係資料庫。為支援分散式應用開發,JBuilder還集成了 VisiBroker ORB、JSP server、資料庫和EJB AppServer,並提供Open Tools API便於第三方工具整合。上述種種的優點使得JBuilder一舉超越Visual Cafe,成為當時最受歡迎的Java開發環境。在眾多Java開發環境中,1999年IBM釋出的VisualAge for Java Micro Edition是比較有特色的開發環境,它是由Erich Gamma和與Erich Gamma有“焦不離孟、孟不離焦”之稱的John Wiegand共同進行設計的,採用了Java 擴充套件機制,並集成了JUnit測試框架,其當時所採用的架構深深地影響了後來Eclipse1.0所採用的架構。同時,通過VisualAge for Java Micro Edition的開發,那些來自“未來世界”(Smalltalk們總認為他們來自計算機的未來世界)的軟體精英們,全面徹底地對Java技術進行了評估,得出了許多結論性的東西,這之中包括現在鬧得沸沸揚揚的Swing和SWT對比。此外,Sun將其收購的NetBeans變成了開源的Java IDE也是一件不大不小的事情。
縱觀1996年至2000年這五年時間裡,隨著Java及其相關開發應用的發展,Java開發環境也不斷的完善,從CLEs進入到IDEs階段。為了提高Java開發人員的開發效率,Java開發環境主要從兩個方面進行改進與提高。一方面是提高整合在Java IDEs當中開發工具的效能和易用性,另一方面是將Java開發環境儘可能的覆蓋到整個軟體的開發生命週期。隨著基於WEB,採用N-層結構的應用開發成為Java開發人員主要從事的開發任務,Java開發環境需要支援越來越多的技術,比如:XML、JSP、EJB和CORBA等,這就造成了Java IDEs的規模變得越來越大,許多Java開發環境都集成了資料庫、JSP Server和AppServer,軟體的研究人員將上述IDEs不斷膨脹的現象稱為“IDEs大爆炸”。
“IDEs大爆炸”現象發生以後,有關Java開發環境是走少而精的發展方向,還是走大而全的發展方向就成了廣大Java開發人員關注的問題。2001年Java開發人員達到了200萬,成為每個軟體供應商都無法忽視的力量,這一年JetBrains推出了Java開發環境少而精的代表: IntelliJ IDEA。 IntelliJ IDEA明確的表示只做最好的Java程式碼編輯器,不做什麼檔案都可以編寫的編輯器。它關注Java開發人員的工作實際並將這些工作進行了優化。由於減掉了一些可有可無的工具,所以價格上相對合理公道。當年IntelliJ IDEA擊敗JBuilder成為最受Java開發人員歡迎的Java開發環境,不過2002年隨著JBuilder將大而全的功力再提升一步,將UML建模工具、JUnit測試框架以及Apache Struts等開發工具整合進來,大而全的發展方向又一次受到Java開發人員追捧。最全還是最好似乎使Java開發人員在選擇Java開發環境時處於兩難狀況,但實際上當Eclipse 1.0釋出時,這個問題已經得到了初步的解決,最好和最全是可以兼顧的。
Eclipse的出現不是從天上掉下來的,也不是某個天才拍腦袋想出來的,它是一群軟體精英們集體智慧的結果。早在1998年IBM就打算開發新一代的工具平臺以便將它現有的各種開發工具統一起來,並減少開發各種工具時重複的勞動,同時希望在新的平臺上建立新的Java開發環境。經過一段時間的準備, IBM開始建立起一個開發團隊,人員構成主要來自VisualAge for Java Micro Edition和VisualAge for Java兩個專案的開發人員,選擇的標準是過去10年至少開發過5到6個IDE。此外,IBM還聯合了9家公司共同成立了一個開源組織Eclipse基金會,將Eclipse提供給開發人員使用,並在開源社群的幫助下進一步完善Eclipse本身。Eclipse在最初設計時,外掛模型是靜態的,不能實現外掛的即插即用功能,即便是大受歡迎的Eclipse 2.1也還是靜態的。所以到2004年釋出Eclipse 3.0時,Eclipse進行了重大改進,採用OSGi的外掛模型,初步實現了外掛的即插即用功能,至此一個完美的、可擴充套件的開發環境展現在Java開發者面前,這時Java開發人員已經達到300萬。
Java開發環境的現狀
2004年Eclipse 3.0的釋出極大刺激了Eclipse使用者的增長,經過一年以後,Java開發人員現在使用Java開發環境的狀況是如何的呢?看了下面的表格裡的資料也許可以瞭解一個大致的狀況。
首先需要指明的是上述的資料並不是當前Java使用者使用Java開發環境的準確反映,但我們可以從中瞭解一個大致的狀況。現在的Java環境可以分為三個集團,第一集團是Eclispe它大約佔據1/3的份額,第二集團是 IntelliJ IDEA、NetBeans 和JBuilder佔據另外1/3的份額,相互之間旗鼓相當,第三集團是以JDeveloper和WSAD為代表的十幾種Java開發環境佔據剩下的 1/3份額,但每種開發環境佔總份額的比重不超過5%。我們考察Eclipse、intelliJ IDEA、NetBeans 和JBuilder這些主流開發環境,可以發覺它們有一個共同的特點那就是可擴充套件,儘管在實現手段上各有不同。這就是為什麼稱現在的Java開發環境為XDEs(eXtended Development Environments)的原因,IDEs已經死亡了4年,專業的開發人員需要了解這個事實,因為XDEs也快死了。
由於市場的壓力,一個軟體企業不僅要提高開發人員個體的工作效率,還要提高整個開發團隊以及整個企業的開發效率,但在現有的Java開發環境XDEs下無法完全做到這些,所以新一代開發環境CDEs (Collaborative Development Environments)就產生。Grady Booch和Alan W. Brown的研究表明一個程式設計師一天工作時間的分配是這樣的:分析佔16%(從5%到40%不等), 設計佔14%(從1%到40%不等),程式設計佔16%(從0%到60%不等),測試佔10%,打電話佔3%,閱讀佔7%(電子郵件,文件,月刊和雜誌),參加開發會議佔10%,無關的會議佔7% 。從這些資料可以發現,開發人員用於交流的時間約佔工作時間的1/3,開發人員的相互交流非常重要。可是現有的主流Java開發環境一般僅將分析、設計、程式設計和測試等工具整合進來,卻未包括用於交流的工具,這顯然不合理。因此,所謂CDEs就是將用於人與人、人與團隊以及團對於團隊進行交流的工具整合進來的開發環境,比如,CDEs常具有傳送電子郵件、進行及時通訊和螢幕分享等功能,通過實現無損耗過程的交流提高開發團隊的開發效率。
現在已經商業化的CDEs是CodeBeamer Collaborative Development Platform和CodePro AnalytiX,上述兩款軟體都提供Eclipse的外掛,可以與Eclipse整合在一起,使Eclipse升級成為一個CDEs。大家肯定知道Borland已經宣佈開發基於Eclipse的新版JBuilder-“Peloton”,Peloton就是一個CDEs(Collaborative Development Environments),當它明年上半年釋出時,就意味著Java開發環境進入CDEs時代,現在Java開發環境還處於XDEs與CDEs交替的階段。
Java開發環境的未來
在可以看得見的將來,Java的開發環境還會是以CDEs的形式存在。開源組織或開發工具供應商將會努力為軟體的開發建立一個絕對光滑的平面 (Frictionless Surface),實現無損耗的開發過程,以提高開發效率。為了實現無損耗的開發過程,Java的開發環境將會關注以下幾個方面:
● 起步階段方面
● 協作開發方面
● 維護開發團隊有效溝通方面
● 多個任務的時間協調方面
● 相互協商方面
● 資料有效性方面
但這裡必須承認未來Java開發環境是如何具體去實現無損耗的開發,還需要時間給與答案,因為現在所能採用的方法未必是最好的,比如,使用面向檔案的 CVS進行協同開發就有需要改進的地方。
總結
羅裡羅唆一大堆,歸納起來不過就是:一個目的、三種手段以及一條規律。
一個目的:十年Java開發環境的演變,其目的就是為了提高開發效率。
三種手段:
● 提高整合在Java開發環境中開發工具的效能和易用性
● 將Java開發環境儘可能的覆蓋到整個軟體的開發生命週期
● 整合人與人、人與團隊以及團對於團隊進行交流的工具
一條規律:軟體開發環境的發展過程是從CLEs到IDEs再到XDEs最後進入CDEs,這是由Grady Booch總結出來的,套在Java開發環境上也適用。
Java虛擬機器的起源與構造
當我們說到“Java”這個詞的時候,指的是四個相互關聯的概念:Java語言、Java API、Java Class檔案格式、Java虛擬機器。整個Java體系是基於Java 虛擬機器構造的,正因為如此,才能實現Java的安全性和網路移動性。Java並非是第一個採用“虛擬機器”概念的體系,但卻是第一個得到廣泛運用的虛擬機器平臺。 “虛擬”,是一種隔離物理資源與邏輯資源的手段。Java虛擬機器的“虛擬”,則是用來隔離物理機器、底層作業系統與Java語言規範實現的手段。
雖然Java是一種面向物件的語言,我們平時大量使用的,是物件間的多型、組合(Composition)、委派(Delegation),但當我們討論虛擬機器的時候,我們看見的基本概念卻是“棧(Stack)”和“堆(Heap)”。根據馮諾依曼的“儲存計算”模型,所有的程式碼都儲存在程式碼空間中,隨著程式計數器指標的變化進行程式的執行、跳轉。Java虛擬機器中沒有暫存器的概念,方法呼叫是採用“棧”進行的,這是一種安全、簡潔的方法。
Java虛擬機器通過類裝載器支援對類的隔離,這也是Java實現安全性的基礎。每個類都具有自己的名稱空間,在具有不同安全級別的沙箱中執行,因此不會產生低安全級別的程式碼來越權訪問高級別程式碼的機會。類裝載器的出現是Java虛擬機器與大部分用C實現的虛擬機器的顯著不同之處。
Java虛擬機器的另外一個顯著特點就是實現了自動的垃圾收集。在往常,寫程式的時候要牢記物件之間的關聯,在每個程式塊中假若申請了物件空間,就必須在出口釋放掉,方法呼叫往往同時也就是物件的邊界。而自動垃圾收集帶給開發者的最大好處,就是可以非常方便地從整體上把系統的物件組織成一張物件圖,只需往這張圖中新增物件,維護物件之間的關聯,卻不需要自己做複雜的清掃工作。正是有了這種思維單純的物件圖的支援,OR Mapping(關係資料庫與物件對映)技術在最近得以大行其道,設計模式也更容易被Java群體所接受。
虛擬機器的優化
1995年第一代的Java出臺之時,其虛擬機器執行是依靠“位元組碼直譯器(Byte Code Interceptor)”的,也就是說每條指令都由虛擬機器來當場解釋執行,這造成速度令人抓狂地緩慢。更有甚者有人開始總結許多的“速度優化經驗”,比如說:“儘量把所有的程式碼都放在較大的方法中執行”與“少用介面”等等,這完全與Java語言的設計目的背道而馳,現在看起來是多麼可笑的奇談怪論,當時卻是很多程式設計師津津樂道的經驗之談。無他,Java本身執行太慢了。Java生命的前十分之三就是如此緩慢地渡過的。
於是,Sun的工程師開始拼命想著提高執行速度。JIT靜態編譯器的出現是在1996年十月,Sun放出了第一個編譯器。JIT編譯器在每段程式碼執行前進行編譯,編譯的結果為本地靜態機器碼,執行速度有了質的提高。Symantec公司當時憑藉其傲人的JIT編譯器,在整個Java界受到熱烈的追捧。在其後的1998年,Java 1.2釋出的時候,附帶了JIT編譯器,從此Java的使用者終於可以拋開上面說的那些奇怪的“速度優化經驗”了。
JIT靜態編譯器雖然可以解決一些問題,但是效能仍然和C/C++有很大的差距。對一段程式而言,一名優秀的程式設計師是如何來改進執行速度的呢?首先,他不會傻到把所有的程式碼都來優化,他會觀察、思考到底哪段程式碼對整體效能影響最大?然後集中精力來優化這一段程式碼。按照經驗,整個程式 10%-20%的程式碼,會佔據 80%-90%的執行時間。用這種方法,在同樣的時間、付出同樣程度的努力後,這名優秀的程式設計師使整個程式的效能得到了很大程度的優化。HotSpot引擎,就是模仿人工的這種方法進行優化的。在程式執行的開始,Java程式碼仍然解釋執行,但HotSpot引擎開始進行取樣(Profiling)。根據取樣的結果,決定某段程式是佔用較多執行時間的,就認為它是“HotSpot”,它也就是目前程式的瓶頸, 引擎開始啟動一個單獨的執行緒進行優化。因為不象原始的 JIT編譯器那樣無差別的編譯所有程式碼,HotSpot引擎可以集中精力來對HotSpot程式碼進行深度優化,這樣這部分程式碼執行起來更加迅捷。之前的靜態編譯器只能按照預定的策略進行編譯優化,而HotSpot引擎的優化是基於取樣的結果的,因此這種方法對所有的應用程式都有效。1999年3月27日,Sun放出了第一個HotSpot引擎。在隨後的2000年5月的JDK 1.3中,包含了HotSopt引擎,這也使1.3成了一個具有里程碑意義的發行版本。到這裡,Java的十年生命,已經過去了一半。
HotSpot代表的是一種動態編譯的技術。對Java這種大量使用委派、組合等面向物件特性的程式來說,動態編譯比起靜態編譯來有顯著的優勢。比如Method Inlining。方法的呼叫是一個很耗時的操作,假若可以把方法呼叫直接內嵌到呼叫者的程式碼中,就可以節省大量的時間, 這被稱為“Method Inlining”。因為涉及到類的過載,靜態優化很難確切知道哪些屬性、方法被過載,因此很難對method進行合併,只好在方法內部進行靜態編譯,假若每個方法都很小,靜態優化能起到的作用也就比較小。而動態編譯因為可以完全隨時掌握類的過載情況,就可以把相關的方法合併進行深度優化。現代的Java程式,特別是在設計模式教育得到普及之後,大量使用類的繼承、委派,形成了很多短小的方法,動態編譯的優勢就更加明顯。
自從出現了HotSpot之後,整個Java界為之一振。
最近的五年,就是繼續優化的五年。繼續進行優化的方法有幾條路,一是研究新的取樣演算法。因為取樣關係到不同的優化策略,會對整體效能有比較大的影響。二是研究深度優化的方法。三是研究垃圾收集的演算法。垃圾收集會帶來程式短暫的停頓,這會帶來負面的使用者體驗。於是,如何提高垃圾收集的效率,減少延遲,出現了五花八門的演算法,比如漸進式收集、火車演算法等。在多處理器的時候,如何利用多處理器進行並行收集也是研究的一個熱點。這方面,BEA的JRocket走在了前面。
現實生活中的虛擬機器
最後,讓我們來盤點一下目前市面上可見的各個虛擬機器。
首先要提到的,毫無疑問是Sun的虛擬機器。作為大眾心目中的“官方實現”,Sun擁有最大的使用者群,並且擁有“相容基準”的地位,其他虛擬機器都必須要考慮和Sun虛擬機器的相容性問題。比如 JRocket就會在某些特殊情況下表現出和Sun不同的特性,可能對程式執行有影響。不過Sun也的確沒有讓廣大使用者失望,雖然在早期效能比不上Symantec,後來在1.2 的時候效能又被IBM超越,但Sun一直在努力革新,特別是 1.4.2之後,效能有了長足的進步。雖然JDK 1.5的虛擬機器在效能上沒有什麼提高,但是增強了穩定性,據說修改了8000處bug,真是讓人汗流不止。原來我們在1.4.2下面一直在享受這麼多bug啊。
其次是老牌勁旅IBM。IBM的JDK在1.3的時代創下了最好的效能記錄,從此樹立了高階形象。特別是在其WebSphere產品中得到了很好的評價。其JDK也是最早支援64bit的JDK之一。到了現在,IBM JDK在高階仍然是和BEA可以一拼的。
然後是後起之秀,BEA的JRocket。說到BEA突然在JVM領域一夜之間異軍突起,多少讓人有些瞠目,不過它採取的戰略特別簡單:自己沒有,索性花錢買了在此領域深有研究的JRocket,在前面加上BEA的標誌就可以了。JRocket瞄準高階伺服器市場,在多處理器環境下有不俗的表現。
除此之外,還有幾個開放原始碼的JVM值得一提。首先就是大名鼎鼎的JikesRVM。說起其大名,大多數人都知道Jikes編譯器是 IBM開發的,效率比同等的javac編譯器高得多,很多開發者都使用Jikes編譯器來取代javac。而JikesRVM則是IBM開源出來的一整套虛擬機器技術,包含了JIT,GC的完整實現,在其網站上也有眾多的論文,實在是想要深入研究JVM者的絕佳資源(http://jikesrvm.sourceforge.net)。
Kaffe是一個老牌的JVM,不過現在已經很少聽到了。作者撰寫此文時,www.kaffe.org網站已經沒有響應,也不知道現在的情況如何了。
GNU則有兩個計劃:GCJ和GNU classpath。GNU classpath是一個底層實現,而GCJ是支援java的預編譯器。
結束語
時光流轉,轟轟烈烈的Java虛擬機器效能爭論彷彿還在耳邊迴響,現在新的爭論卻已經是“Java的效能是否已經超越C/C++”。Joakim Dahlstedt 是 JRockit 的主要架構設計師之一,他堅持認為,Java絕不是一種速度慢,效率低的語言,JVM 是一個關鍵的元件,確保了系統的部署與執行和開發一樣快速、輕鬆。特別是在目前開發趨勢是採用大量預製的框架時,動態編譯有可能比C/C++這樣的靜態優化獲得更好的效能。
Java本來就是為了嵌入式系統而生
1990年12月,Sun內部由James Gosling、Patrick Naughton以及Mike Sheridan成立了一個叫做Green Team的小組。Green Team小組的主要目標,是要發展一種新架構,而這種架構必須能夠在消費性電子產品作業平臺上執行,現在我們普遍認識的PDA、手機或是資訊家電(IA),都是屬於這種架構的目標平臺。接著,Green Team在1992年的9月3號,發表了一款由Java 技術之父 James Gosling所領軍研發,名叫Star Seven(*7)的機器,研發出一部互動式的掌上型家用娛樂裝置,可透過使用動畫觸碰式螢幕的使用者介面來控制其它電子裝置。
經過了13年的時間,現在我們檢視J2ME的發展歷史,我們可以發現,雖然在1999年,Java被切割成J2SE、J2ME、J2EE,所以有了J2ME這個名詞的出現。但是Java並非1999年開始才開始發展嵌入式系統上的應用。其實,Java本來就是為了嵌入式系統而發展的一種架構。即使目前大家多半將Java的應用聚焦於企業上的J2EE應用。但是嚴格來說,J2ME才是Java真正“迴歸本心”的領域。
半路殺出的Personal Java
Personal Java是正規Java版本的一個分支,其目的在於能夠讓PDA或高階手機執行Java程式,目前在Windows Mobile或Symbian OS(僅限採用UIQ或Nokia Series 80的行動電話)平臺上都可以開發Personal Java應用程式。
雖然從Java 1.0發表之後,Java就被廣泛地使用在桌上型應用程式以及Applet的開發上,但是,從Java 1.1開始,Java又回到了它一開始的老路-也就是嵌入式系統方面的應用,在當時Sun Microsystems發表了Embedded Java與Personal Java(也有人簡稱為PJava)這兩項規格。Personal Java的規格是從Java 1.1之中所分支出來,因此Personal Java的規格是根據Java 1.1的規格而制定的,但是並非Java 1.1的全部規格都包含進來,所以Personal Java只能算是Java 1.1平臺的子集合。
Personal Java特別適合用在具有豐富圖形顯示能力的消費性電子產品上面,於是我們可以發現Sun Microsystems網站上對於Personal Java的參考實作是建立在Windows Mobile產品(過去叫做Pocket PC)上頭的。
在1999年,一般PDA或手機的能力,離Personal Java所需要的硬體條件仍有很大的一段差距,因此Personal Java並不是一個很成功的產品。因此Sun Microsystems在此時將Java區分成J2SE、J2EE、J2ME這三塊,希望可以重新塑造整個架構,尤其是J2ME,希望Java可以在嵌入式系統的領域有所發展。
J2ME從何而來?
談到J2ME,大家就會聯想到KVM這個名詞, KVM的設計者Antero Taivalsaari,最早在Sun Microsystems參與Spotless Project,這個專案才是J2ME的最早起源。由於Antero Taivalsaari曾經在世界知名電信裝置製造商工作,所以他有了在手機上開發JVM的概念,後來得到公司支援,就有了各位所知的KVM(K Virtual Machine)。
最早應用KVM的產品,就是一個可以在Palm OS上執行的KJava。KJava並不算是一個正式產品,只能算是一個概念測試產品。開發人員會開發名為Spotlet的應用程式,透過工具和KVM的輔助,應用程式就可以在PDA上執行。雖然KJava早已成為過去式,但是仍有電信廠商使用這個名詞,作為手機上Java平臺的名稱,不過,已經不是真正的KJava了。有了KJava的發展經驗,Sun著手設計J2ME的架構,讓J2ME可以應付未來嵌入式系統的發展。
J2ME整體架構
J2ME最基本的規範制定在JSR-68(Java規格編號第68號),在此規格里頭定義了J2ME的技術架構。根據此規範,J2ME由三種類型的規範堆疊而成,分別是Configuration、Profile以及Optional Packages。這三種類型的規範定義由其它的規範所定義。
在最底層的Configuration規範,定義了硬體所必須具備的能力,比方說硬體至少具備多少ROM、RAM,CPU的頻率最少應該是多少,連線網路時頻寬至少要多快。Configuration規格之中定義了一組低階的API,這代表Java至少必須提供的低階功能,這組低階的API就是核心類別函式庫的子集合。
在Configuration之上的規範稱為Profile。Profile針對各種不同機器的特性定義了高階的API,這些高階的API通常都是與其它平臺不相關的擴充類別函式庫。這些高階API決定了該種機器上Java程式的撰寫方法。比方說行動通訊裝置(手機、PDA等)這型別裝置上Java程式的撰寫方式,以及能夠呼叫的API,都定義在MIDP(Mobile Information Device Profile)之中。
就算是同類型的裝置,有些功能也不一定具備(有些廠商的機器可能有,有些廠商的機器可能沒有,例如手機上的照相機、和絃鈴聲等),這些功能就定義在“廠商選擇性實現套件(Optional Package)”之中,比方說,有的廠商會提供簡單的資料庫管理系統(DBMS)在該裝置上,那麼他們就會實現JDBC Optional Package。不提供資料庫管理系統的廠商就不需要實現JDBC Optional Package。所以稱作廠商選擇性實現套件。
所謂的廠商選擇性實現套件,意思是說,這是一組和其它規格(或API)沒有任何相依性的類別函式庫,如果廠商願意提供這樣的功能給程式設計師(通常是因為硬體具有充分的能力可以完成規格之中所制定的功能),就會將這組類別函式庫實現出來,程式設計師也可以利用這些功能開發出功能更多的應用程式。
MIDP工業標準
雖然J2ME架構完整,但是目前的發展,除了Personal Profile之外,最大的應用在於架構在CLDC之上的MIDP。目前所有標示可以支援Java的手機,所支援的都是MIDP,幾乎所有的無線通訊廠商皆採用MIDP作為其開發程式的標準。
在MIDP 1.0的時代,由於規格上本身的功能不足,使得許多廠商不得不加入自己專屬的API,例如震動、背光、聲音等擴充功能(例如:Nokia UI API),以彌補MIDP平臺的不足。
到了MIDP 2.0,增加了許多眾所期盼的功能,但是,即使規格更清楚了,即使很多新功能都已經由JCP制定成標準的Optional Packages,這些問題依然無解。市面上的MIDP平臺仍然處於混亂狀態。開發者必須在執行時期偵測各種專屬API和Optional Package的存在,這會增加多餘的程式程式碼。平臺的混亂會造成在某個裝置上可以順利安裝及執行,而到了其它裝置時,有可能無法執行,甚至有可能連安裝都有問題,所以開發者通常要開發好幾種版本的MIDP應用程式供各種廠牌、各種型號的裝置使用。
為了解決上述問題,進一步提高MIDP應用程式的可移植性,Sun Microsystems以MIDP 2.0規格為核心,設計了JTWI規格。未來的無線通訊平臺,將不會只有符合MIDP 2.0規格,而是必須要符合JTWI規格。這將是J2ME軟體在可移植性上的一大突破。JTWI(Java Technology for Wireless Industry)是一個統合性的規格,其目的是為了確保MIDP軟體的可移植性。所以JTWI規格除了規範無線通訊平臺(特別是手機)所必須支援的J2ME標準之外,也對既有規格中模糊不清的地方與以加強。所以新款的手機為了加強移植性,都會支援JTWI標準。JTWI只是一個統合性的規範,並沒有制定任何新功能,目的只是要統一當前平臺混亂的現象,讓J2ME應用程式更具可移植性。JTWI主要分成幾個部分:
1 .規定平臺必須支援的API。
2 .統一的應用程式執行環境。
3 .既有規格的理清與加強。
在規定平臺必須支援的API的部分,JTWI規定至少必須支援CLDC 1.0、MIDP 2.0以及WMA 1.1:
所以,只要廠商宣稱支援JTWI平臺,那麼代表一定支援CLDC 1.0、MIDP 2.0以及WMA 1.1規格之中的所有功能。另外,廠商可以根據裝置本身的能力,將CLDC 1.0提升成CLDC 1.1,可以加入MMAPI 1.1。因此實際上JTWI平臺會有一下幾種組合方式:
其中,CLDC 1.1 + MIDP 2.0 + WMA 1.1 + MMAPI 1.1是最完整、功能最強平臺。
在統一應用程式執行環境方面,過去讓J2ME應用程式開發者最為頭大的問題有以下幾項:
● 應用程式的大小可以多大?
● 執行時期的記憶體有多少可以使用?
● 有多少記憶體空間可以作為永久儲存之用?
由於規範中對於J2ME應用程式本身的大小和執行環境沒有很詳細地規範,使得每家廠商都有自己的規範,比方說Nokia限制應用程式最大隻能30 KB,Motorola則可以支援50 KB以上的應用程式。這些規範都嚴重地困擾著開發人員。這些問題在JTWI之中都獲得改善。
JTWI定義了應用程式的標準大小(Standard-size Application)。JTWI規定,可以執行J2ME應用程式的行動通訊裝置,至少可以容許大小為64 KB以上的程式主體(JAR檔案)、5 KB以上的應用程式描述檔案(JAD檔案)、以及30 KB以上的永續儲存空間、執行時期的記憶體(Heap Memory)為256 KB。上述大小隻是底線,廠商可以視裝置的實際能力支援更大的記憶體空間。標準應用程式大小(Standard-size Application)將成為一個計算用的單位,舉例來說,廠商會說這個裝置可以安裝20個標準應用程式,開發者所撰寫的程式可以說這個程式需要佔掉3個標準應用程式的空間。
至於對既有規格的理清與加強的部分,我們將在往後章節一一說明。最重要的一點是,JTWI規定,該裝置所支援的任何媒體格式(例如圖片、聲音、影像等)都應該能夠使用HTTP 1.1獲取,也就是說,存取這些媒體時所使用的URL都必須能夠接受http作為存取的通訊協議。
起點
在“J2EE”這個縮略語被第一次介紹給世人的時刻,也許沒有幾個人可以預料出它在日後的奇特歷程。那是在1999年6月的JavaOne年會上,時任Sun公司Java企業開發部門主管的Mala Chandra興奮地預告了Java世界的這位新成員。那些不熟悉背景的聽眾們,揣摩著她演說中出現的一串串全新術語,表情大概又是驚喜、又是迷惑:一個完整的“多層企業開發架構”、以“容器”和“元件”的形式提供服務、一套“廠商中立的開放技術規範”、對開發者隱藏了不同平臺和“中介軟體”的技術細節、實現了企業級應用間的“無縫整合”等等。在今天的開發者看來,這些似乎都已經是老生常談,但在當時的場景下,閃動在幻燈片上的每一個口號,都意味著聽眾們事後又要經歷一段困難的學習過程。
幸虧Chandra有一副了不起的口才;這位本科念建築學的印度裔高層主管,談起軟體架構來也有特強的空間想象力。她清晰地說明了設計J2EE架構的兩個初衷:首先,對於廠商,J2EE意味著一套開放標準,加入這個標準,他們的產品就可以執行在各種不同的作業系統和工作環境下,成為一個成熟的企業運算體系中可替換的部件;其次,對於開發者,J2EE是一套現成的解決方案,採用這個方案,企業應用開發中的很多技術難題(包括跨平臺移植、事務處理、安全性等等)就會迎刃而解,“資訊像一條不間斷的河流,經過各種各樣的平臺和裝置,從企業應用系統的這一端流向那一端”。
要想理解這段話在當時的實際效應,我們仍然要把時間指標撥回1999年。除了預備迎接千年蟲之外,99年你做了什麼?為了回答這個犀利的問題,我翻出6年前的工作記錄,發現了自己那時參與的一個專案的規格說明書,它正好能提供一幅“Java企業開發”在1999年的標準照。這是一家日本知名IT廠商的企業資訊管理系統,執行在NetScape 3.0 Gold瀏覽器中的Java Applet介面,通過一個專用的中間層系統與Oracle 8資料庫連線。這個中間層已經相當現成、完善,能夠提供遠端物件呼叫、事務處理等一系列的底層服務;留給我們的任務只是完成伺服器端業務物件程式碼,以及相應的客戶端互動開發。
除了Applet客戶端有些特別之外,上述系統與今天常見的J2EE架構很接近;尤其是業務物件編碼也由home類、PK(主鍵)類、entity類等部分構成,很多機制都與EJB如出一轍——只不過這些類並沒有繼承javax.ejb包的介面,而是採用了專用的API。它與EJB之間的相似不像是偶然的,設計者肯定參照了Sun在1997年底推出的EJB 1.0技術規範。
換言之,在J2EE誕生伊始的語境中,市面上已經存在著很多程度不一的“準J2EE中介軟體”了。它們主要用於解決三大類問題:事務處理、分散式物件管理和Web請求處理。首先,事務處理管理器(Transaction Processing Monitor)一直是高階企業計算領域的熱門產品,著名的應用伺服器廠商BEA,正是通過收購事務處理軟體Tuxedo進入中介軟體市場的。另一方面,從90年代初開始,越來越多的人把“N層分散式物件架構” 當成傳統的客戶端/伺服器架構的替代方案。那時剛剛興起的CORBA技術是推動這一趨勢的重要力量(比如說,前面提到的那個由日本廠商自行開發的專用中間層,就採用了CORBA作為基礎架構)。最後,Java技術在Web領域中的應用也是當時初露頭角的熱點。1997年6月,Sun在釋出一款“Java Web Server”的同時第一次公佈了Servlet API;沒想到這項技術副產品(連同1998年問世的JSP)正好迎合了廠商的戰略需要。對於上面提到的N層架構來說,HTTP服務是一個非常理想的前端;所以基於Java的Web引擎,也在此時成了企業級Java解決方案的一個必不可少的部分。
Java、Web、事務、分散式物件,這幾股開發潮流匯合在一處,形成了當時最熱門的產品“應用伺服器(Application Server)”或“中介軟體(Middleware)”。為了給定語“最熱門”作個註釋,我們可以參照一下BEA公司在1998年收購Web應用伺服器廠商Weblogic的成交價:1.92億美元。而這並不是一樁孤立的收購,NetScape和Sun也以相近的價格買下了另外兩家企業Kiva和NetDynamics。而這也正是J2EE規範出臺的背景:幾乎所有要廠商都推出了、或是正在趕製自己的應用伺服器產品,但這個“應用伺服器”究竟應該是什麼東西,競爭者們又各有表述、莫衷一是。
說到這裡,我們才梳理出了J2EE技術規範的第一個版本在1999年12月問世的實際意義。首先,它為Java企業開發提供了一幅清晰的全景,各項分支技術在這個領域中的地位和作用得到了客觀、準確的定義。至此大家才對一個Java企業解決方案的構成要素有了基本共識。其次,它使用“容器”和“元件”等概念描繪了Java企業系統的一般架構,明確地劃分了中介軟體廠商和應用開發者的職責所在。最後(但絕非最不重要地),J2EE通過一套公開標準規定了應用伺服器產品的具體行為,在執行此標準的廠商產品之間實現了一定程度的可替換性和互操作性。當時的媒體用“B2B開發的預設標準”之類的說法歡呼這項里程碑式的成就——那些撰稿人哪裡知道,在J2EE與那個被稱為“B2B” 的短命新貴之間,其實並不會有太多故事發生;同樣,他們也不會想到,J2EE要想成為一種真正成熟的開發正規化,前方還有一段遠為艱辛的旅程。
社群的形成
記得Kruglinski在名著《Inside Visual C++》的某個版本中給出了一個Web瀏覽器的程式碼例子;在這一節的開頭他說到:如果你幾年前開發了一個Web瀏覽器,那肯定會給你帶來上千萬的收益;但如果你現在才想到開發這個東西——那也就是個C++語言的練習罷了。在今天的程式設計師眼中,應用伺服器似乎也成了價格低廉(如果不是全然免費)的日用消費品。所以,想要理解它們在那幾年的大行其道,就非得藉助Kruglinski這樣的智慧不可。在1999年底,市面上可以找到30種以上自稱“Java應用伺服器”的產品,可見當時這類軟體是網路風險投資的寵兒。但是此時出臺的J2EE規範就像是一陣席捲整個產業的勁風,在一夜之間,所有人都有了判斷什麼是一個“應用伺服器”的權威途徑。
為了獲得一張J2EE競技場的入場券,各家廠商面臨兩項考驗:首先,要具有能夠覆蓋J2EE中所有主要技術的產品線。這在當時是一項非常苛刻的要求,在沒有開源產品可供參照的情況下,短時間內推出包括EJB容器、Web引擎和JMS中介軟體的整體解決方案,這決不是隨便哪家創業公司都能辦到的。完成了若干次成功的併購之後,BEA在這一點上搶佔了先機,完整的產品線使它成了人們心目中的首選J2EE平臺提供商。其次,要讓產品通過Sun的J2EE相容性測試。要做到這一點同樣不易:就連IBM的WebSphere也一時還沒達到百分之百的EJB支援。到2000年底為止,共有15家廠商能夠提供完整的J2EE解決方案,其中9家(包括Sun本身)實現了“J2EE相容”,他們中間包括了日後這個領域的主要競爭者。毫無疑問,這是一次非常殘酷的行業洗牌,但留在場內的廠商也相應地形成了推動J2EE發展的主體力量。
上面說過,在它的孵化階段,Sun的J2EE團隊主管是女強人Mala Chandra,她本人雖不是工程師出身,但對技術有著很強的感知能力和想象力;J2EE一出臺就能夠為人們提供一幅完整、直觀而不失深邃的圖景,此中當然有Chandra本人的大量貢獻。在她直接領導下工作的幾位工程師,也都是Sun內部非常傑出的人才。無論是制定了JDBC、JMS等規範的Mark Hapner、JavaMail的設計者Bill Shannon,還是EJB的主要設計者Vlada Matena,後來都是業界一言九鼎的技術領袖。這個班子的合作時間並不太長:2000年左右的那個時期正是IT界創業的黃金年月,Chandra很快就和Sun公司Java部門的總裁(也是創造Java的功臣之一)Alan Baratz一起,到一家剛起步的Email中介軟體公司Zaplet淘金去了;捷克裔的開發天才Matena也離開Sun開辦了自己的公司。留下的兩個人Hapner和Shannon先後擔任了J2EE技術的首席設計師。
多年以後,Hapner回憶起J2EE初創的那個時期,深感如今Sun對Java的左右能力已經大不如前:“現在,Java事實上屬於整個技術社群,它的發展有賴全體參與者的推動。”的確,如今Sun已經不太可能重演當年的開拓性功績,很難再為一個已經成形的領域重繪版圖。但正如上文所說,即使是在1999年,J2EE設計者們面對的也不是一張從未著墨的白紙。他們的設計始終要以各大廠商的現有產品為出發點,這也是天才的設計師們做出的設計卻遠非完美的原因之一:與從頭設計一門全新的程式語言不同,J2EE規範從一開始就是各方博弈和妥協的產物。
很容易注意到,J2EE與Java社群的決策機制JCP(Java Community Process)是幾乎同步產生的。J2EE下屬的各種技術規範,包括1.4版之後的J2EE本身,都作為待決規範議案(JSR,Java Specification Request)被納入了JCP的議程。這些議案的審議過程很少是一帆風順的,幾乎每一個都要經歷18個月以上的拉鋸戰。在多項技術規範的審議過程中,我們都見到了這樣的現象:最初列名審議委員會的某家主要廠商,沒能等到該規範通過就已經被收購或倒閉了。與微軟在.NET平臺上的乾剛獨斷相比,J2EE發展中的這個“牛步”特徵雖說是審慎和民主的表現,但終歸不符合軟體演化應有的速度。
J2EE社群中的另一股重要力量,當然是種類極為豐富的開放原始碼專案。2002年以來,在J2EE領域的各個層面上,幾乎所有主流產品都有來自開源專案的替代方案,在其中很多位置上,開源產品反而是勝過商業產品的首選。但請別誤解,這裡的“開源”並不意味著完全的自動自發,J2EE世界中的開源專案也與Linux或PHP世界頗為不同。在很多非常成功的J2EE開源專案背後,我們都能發現商業機構的推動作用:Apache的Jakarta社群是IBM扶植的結果;實現了開源應用伺服器JOnAS的ObjectWeb,則是許多法國IT廠商(包括若干政府部門)合資支援的一個聯盟組織……這些有商業背景的開源專案資金雄厚,人員齊整;更重要的是,從投資者到開發者,參與這些專案的很多人都體現了軟體工業中難得的非功利心態,因而最終推出的產品質量甚至高於同類型的商業軟體。在主流廠商之外,它們是支撐J2EE大廈存在的一組基石。
另一方面,不少開發者也間接地通過自己的開源產品獲得了可觀的盈利。這些人大多以免費的開源產品為依託,以收費方式提供附加的諮詢、方案實施以及技術支援服務。Marc Fleury,開源應用伺服器的JBoss創始人,不無矛盾地把自己倡導的這種商業模式稱為“職業開源開發”。
無論叫它什麼,高階產品的開源化/免費化運動註定要在J2EE產業的發展過程中製造顯著的後果。“JBoss的行徑惡化了J2EE的商業環境,”這是McNealy先生2002年的著名論斷。他的推理過程如下:只有做好商業推廣,J2EE產品才能最終擊潰邪惡的.NET平臺;但開源伺服器會降低主流廠商的銷售利潤;銷售利潤越低,用於商業推廣的預算就越少;因此,整個J2EE陣營都將受損於JBoss。
但在狂熱的開源運動支持者看來,以上論證的大前提就是可疑的。“難道只有會做廣告的軟體才是好軟體?MySQL有過多少廣告預算”爭論的雙方都認為對手誤解了軟體商業模型的實質。究竟誰才掌握了這裡的真理呢?也許只有根據J2EE的未來——也就是它的目標和終點(Telos)——才能做出最終的裁決。
技術的離心力
考察事物的演化,通常有兩種對立的方法。考古學家(Archaeologist)探究肇始和起源;目的論者(Teleologist)則揭示目的和終點。對於前者,“開端(希臘語Arche)”從根本上決定了此後的發展,參天大樹的繁茂都包含在種子最初的萌芽中;而對於後者,“目的(Telos)”才是事物的根本和旨歸:誰沒見過樣態完善的樹,誰也就沒法弄懂種子到底是怎麼回事。
在J2EE五年之後,人們只能交替地用這兩種目光審視它的演化歷程。它的起源與它的目的、“它從何處來”與“它往何處去” 的問題緊密地交織在一起,誰拾起了其中的一個,誰也就要連同另一個一起回答。
今天的J2EE在多大程度上符合它的初衷?回答這個問題並不涉及對J2EE技術成敗的評判,而只是要考察一下:它是否還執行在最初開闢的那個空間之中。在事務處理、物件分佈化和Web請求處理這三個方面中,也許J2EE對事務和Web保持了一貫的忠誠。我們記得Fleury喜歡重複的一個信條:“He who owns the transactional Web owns the Web(誰掌握了帶事務處理的Web,誰就掌握了Web)”Web介面是今天大部分J2EE應用暴露的唯一介面;而雖然事務處理的常用方法已經有了很大改變(藉助AOP機制,很多非EJB架構的系統也自如地實現了宣告式的事務處理),但對事務的重視當然仍將是J2EE開發中的要素之一。
換言之,在5年的演化中,J2EE發生的最大變化可能就在於它放棄了對“分散式物件模型”的強調。EJB2.0引入的本地介面使得Web層與EJB層可以執行在同一個Java虛擬機器中,從而使Web容器與EJB容器的物理分離部署變成一種昂貴的冗餘;J2EE 1.4以後版本支援的Web Services相容性,使得客戶端可以通過粗粒度的Web介面呼叫遠端服務——這兩次變化事實上都是在論證“分散式物件架構”的無用性。人們發現,同一系統的各個分層最好採用細粒度介面呼叫,並且執行在同一個程