Linux 平臺和 Java 平臺有著久遠的但有經常經歷曲折的關系。建置高效能虛擬機器的同時又要跟上日益增長的核心 Java API 集合,這樣做所帶來的復雜性在很大程度上使開發 Java 平臺的開放來源程序代碼「Clean Room」實作的早期行動困難重重。Java 技術的特許實作最終可用于 Linux,但這些實作并不是開放來源程序代碼。因此,大多數 Linux 分發版沒有包括該特許實作。
盡管有這些困難,Java 平臺還是提供了許多好處,從而導致在 Linux 上越來越多地使用該特許實作,尤其是對于服務器應用程序。在本文中,我回顧了 Java 平臺給服務器應用程序帶來的優點,然后研究了在 Linux 上簡單且安全地部署 Java 服務所涉及的問題。作為一個實際范例,我將討論設定 Apache Software Foundation 的廣泛使用的 Tomcat Java servlet 引擎的詳細信息以用于獨立作業。
為什么使用 Java 平臺?
有許多原因可以解釋為什么 Java 平臺成為基于服務器的商業應用程序的廣為接受的選擇。我將主要討論我認為對于該環境至關重要的三個原因︰跨平臺兼容性、受管執行時環境和易于開發。
Java 應用程序提供了跨多種操作系統和硬件平臺的二進制兼容性。對于非 GUI 服務器應用程序尤其是這樣,在此類別應用程序中,通常在實際目標系統中需要執行非常少的測試。工作人員可以在任何他們喜歡的平臺上進行編碼和除錯,同時仍可以將這些應用程序部署到他們也許不能直接控制的環境中。
Java 虛擬機器(Java Virtual Machine,JVM)環境的執行時特性以幾種方式來加強程序安全性。最顯著的方面之一是嚴格的類別型檢查、數組邊界檢查和自動垃圾收集的組合徹底防止了最具破壞性形式的服務器程序代碼攻擊︰緩沖區溢位、重復釋放的錯誤和游離的指針。Java 語言早期用于 applet,經過不斷發展,該語言還有一個完善的系統,用于對那些已確信存在安全性風險的設施進行細微的存取控制。這些方法可供獨立應用程序選擇使用,但它們已建置在許多 Java 服務的架構中。
這些執行時程序安全特性還提供了用 Java 語言開發的便利性。要對便利性這類別問題作任何精確測量是困難的,但大多數具有諸如 C 和 C++ 之類別語言背景而轉向 Java 程序化的工作人員都承認在轉變之后他們的生產力提高了。其中部分是因為在編譯時和執行時嚴格執行類別型確定,以及自動內存管理的簡單性。另一個因素是為 Java 平臺開發的標準 API 擴充的集合。這些 API 對于新的工作人員可能是一個重大挑戰,但是一旦學會了,API 會為各種企業需求提供優秀的跨平臺支持。
當然,對于某些應用程序而言,Java 平臺可能是一個糟糕的選擇。盡管 JVM 體系結構在持續改進,但 Java 應用程序通常會比使用相同算法的 C 或 C++ 應用程序執行得稍微慢一點。根據我的經驗和測試,我估計這個速度差異對于在特許 JVM 上執行的大多數服務器應用程序來說大約是在 20% 到 50% 的范圍內,然而這很大程度上取決于程序代碼的質量。與獨立程序相比,在這些 JVM 上執行的 Java 應用程序還忍受著比較慢的啟動,但是這對于長時間執行的服務器應用程序通常并不是一個重大問題。在大多數情況中,降低的效能和較慢的啟動祇是為獲得 Java 平臺的增強的安全性和更快速的開發優點所付出的微小代價。
開放來源碼替代選擇
除了標準特許 JVM(免費使用,但是來源碼受到限制;可用于 Sun、IBM、BEA 和 Blackdown 組織的 Linux)之外,對于 Linux 還有其它幾個替代選擇。這些選擇包括「Clean Room」開放來源碼 JVM 實作,其中使用最廣泛的可能是 Kaffe(在許多 Linux 分發版中都包括它)。Kaffe 是一個非常有意義的項目,它已經完成了一些令人驚訝的工作,但它只能提供與目前特許 JVM 有限的兼容性。因此,它通常無法使用于本文所關注的企業類別型的服務器應用程序。
用于 Java 程序的本機程序代碼編譯器的開放來源碼工作也有幾個替代選擇。這里最重要的項目是 GNU 編譯器集(GNU Compiler Collection)的 GCJ.使用諸如 CGJ 之類別的本機程序代碼編譯器會將獨立于平臺的 Java 字節碼在其執行之前轉換成特定于平臺的程序代碼(這與在 JVM 中執行成對比,在 JVM 中執行通常在執行時將字節碼轉換成特定于平臺的程序代碼)。
本機程序代碼編譯顯示出它極有可能成為一種避免在 JVM 中執行的 Java 應用程序啟動較慢的方法。但是,使用這種方法的編譯器通常都不能與當代特許 JVM 的穩定狀態效能相匹配。如果 Java 應用程序使用 Java 平臺的動態特性(如使用反射來存取字段或加載在執行時選擇的類別),這種情況尤其突出。根據所使用的實作和編譯選項,本機程序代碼編譯也許還會削弱 Java 平臺的許多執行時安全特性。最后,由于許可證問題,許多 Java API 不能與已編譯的本機程序代碼一起使用。由于這些限制,本機程序代碼編譯目前還不是 Java 平臺服務器應用程序的一個好選擇。
C# 怎么樣?
與 Java 執行時環境有許多共同點的一個替代方法是 Microsoft 的 C# 語言和相關的公共語言執行時(Common Language Runtime,CLR)。C# 是 Java 語言的關系緊密的衍生物,CLR 可能容許 C# 在許多平臺上使用。CLR 還提供了 JVM 的許多執行時安全特性(盡管有嚴重削弱安全保證的逃離出口)。Microsoft .Net 實作還支持預編譯成本機程序代碼的選項以獲得更快速啟動,這與 GCJ 對 Java 字節碼所做的工作相同。當然,Linux 使用者并不能直接使用這項功能,因為 .Net 只適用于 Windows 系統。
Mono Project 正致力于為多種 Linux 產品建置「CLean Room」開放來源碼 C# 和等價于 CLR 的產品。現在,該項目中的 C# 編譯器已開發完成,而且還完成了大部分的 CLR,Microsoft 已發布將它用于標準化。但是,無論從效能還是功能角度來看,在它成為合理的 Java 平臺替代選擇之前還有許多工作要做。CLR 只包括了與 Java 核心類別庫等價的基本內容。在可以將它看作是企業軟件開發的合理選項之前,還需要用許多額外 API 來補充它。
Mono Project 正在致力于開發 CLR 以外的 .Net 其它部分的移植,如果這些移植成功了 ─ 并且如果 Microsoft 不對 .Net 的這些部分強加它的專利權 ─ 那么它們會有助于滿足 C# 成為 Linux 上服務器軟件開發的可靠平臺的需要。但要使那些假設成為現實,還需要做很多工作,同時,Java 程序的本機程序代碼編譯器和開放來源碼 JVM 向那些確實想要避免使用特許 JVM 并可以忍受有限功能性的使用者提供了比較穩定的替代選擇。