深入理解 Java 虛擬機——走近 Java
Java
總述:Java 不僅是一門編程語言,還是一個由一系列 計算機軟件 和 規範 形成的技術體系,這個技術體系提供了完整的用於軟件開發和跨平臺部署的支持環境,並廣泛應用於
嵌入式系統。
移動終端 。
企業服務器 。
大型機等各種場合。
特點:Java 能獲得如此廣泛的認可,除了它擁有一門 結構嚴謹、面向對象 的編程語言之外,還有須有不可忽視的有點,主要有如下幾點。
它擺脫了硬件平臺的束縛,實現了 一次編寫,到處運行 的越界問題。
它實現了 熱點代碼檢測 和 運行時編譯及優化 ,這使得 Java 應用能隨著運行時間的增加而獲得更好的性能。
它有一套完善的應用程序接口,還有無數來自商業機構合開源社區的第三方類庫來幫助它實現各種各樣的功能。
1.2 - Java 技術體系
從廣義上講,Clojure、JRuby、Groovy 等運行於 Java 虛擬機上的語言及其相關的程序都屬於 Java 技術體系中的一員。如果僅從傳統意義上來看,Sun官方所定義的 Java 技術體系包括以下幾個組成部分
Java 程序設計語言。
各種硬件平臺上的 Java 虛擬機。
Class 文件格式。
Java API 類庫。
來自商業機構和開源社區的第三方 Java 類庫。
我們可以將 Java 程序設計語言
JVM 結構圖如下所示
JVM 結構圖
Java Language 體系圖如下所示
深入理解 Java 虛擬機——走近 Java
Java Language
Java 技術體系可以分為4個平臺,分別是
Java Card:支持一些 Java 小程序(Applets)運行在小內存設備(如智能卡)上的平臺。
JavaSE(Standard Edition):支持面向桌面級應用(如 Windows 下的應用程序)的 Java 平臺,提供了完整版的 Java 核心 API,這個版本以前也稱為 J2SE。
JavaEE(Enterprise Edition):支持使用多層架構的企業應用(如 ERP、CRM 應用)的 Java 平臺,除了提供 JavaSE API 外,還對其做了大量的擴充並提供了相關的部署支持,這個版本以前稱為 J2EE。
1.3 - Java 發展史
從1996年 第一個 Java 版本誕生到現在已經有了20幾年時間,其中誕生了無數和 Java 相關的產品、技術和標準,讓我們一同回顧下 Java 的發展軌跡和歷史變遷。
Java-version-history
1994-04:由 James Gosling 博士領導的綠色計劃(Green Project) 開始啟動,此計劃的目的是開發一種能夠在各種消費性電子產品(如機頂盒、冰箱、收音機等)上運行的程序架構。這個計劃的產品就是 Java 語言的前身:Oak(橡樹)。Oak 當時在消費品市場上並不算成功,但隨著 1995 年互聯網潮流的興起,Oak 迅速找到了最適合自己發展的市場定位並蛻變成為 Java 語言。
1994-05-23:Oak 語言改名為 Java,並且在 SunWorld 大會上正式發布 Java1.0 版本。Java 語言第一次提出了 Write Once, Run Anywhere 的口號。
1996-01-23:JDK 1.0 發布,Java 語言有了第一個正式版本的運行環境。JDK 1.0 提供了一個純解釋執行的 Java 虛擬機實現(Sun Classic VM)。JDK 1.0 版本的代表技術包括:(Java 虛擬機、Applet、AWT 等)。
1996-04:10個最主要的操作系統供應商申明將在其產品中嵌入 Java 技術。同年 9月,已有大約 8.3 萬個網頁應用了 Java 技術來制作。在 1996年5月底,Sun 公司於美國舊金山舉行了 首屆 JavaOne 大會,從此 JavaOne 成為全世界數百萬 Java 語言開發者每年一度的技術盛會。
1997-02-19:Sun 公司發布了 JDK 1.1,Java 技術的一些最基礎的支撐點(JDBC 等)都是在 JDK 1.1 版本中發布的,JDK 1.1版本的代表技術有(1.JAR 文件格式、2.JDBC、3.JavaBeans、4.RMI)。Java 語法也有了一定的發展,如內部類(Inner Class)和反射(Reflection) 都是在這個時候出現的。
1998-12-04:JDK 迎來了一個裏程碑式的版本 JDK 1.2,工程代號為 Playground(競技場),Sun 在這個版本中把 Java 技術體系拆分為 3 個方向,分別是:
面向桌面應用開發的 J2SE(Java 2 Platform,Standard Edition)
面向企業級開發的 J2EE(Java 2 Platform,Enterprise Edition)
面向手機等移動端開發的 J2ME(Java 2 Platform,Micro Edition)。
在這個版本中出現的代表性技術非常多(EJB、Java Plug-in、Java IDL、Swing 等),並且這個版本中 Java 虛擬機第一次內置了 JIT(Just In Time) 編譯器(JKD 1.2中曾並存過3個虛擬機,Classic VM、HotSpot VM 和 Exact VM,其中 Exact VM 只能以外掛的形式使用 JIT 編譯器)。在語言和 API 級別上,Java 添加了 strictfp 關鍵字與現在 Java 編碼中極為常用的一系列 Collection 集合類。
1999-04-27:HotSpot 虛擬機發布,HotSpot 最初由一家名為 Longview Technologies 的小公司開發,因為其優異的表現,這家公司在 1997 年被 Sun 公司收購了。HotSpot 虛擬機發布時是作為 JDK 1.2的附加程序提供的,後來它成為了 JDK 1.3 及之後所有版本的 Sun JDK 的默認虛擬機。
2002-02-13:JDK 1.4發布,工程代號為 Merlin(灰背隼)。JDK 1.4 是 Java 真正走向成熟的一個版本,Compaq、Fujitsu、SAS、Symbian、IBM 等著名公司都有參與甚至實現自己獨立的 JDK 1.4。仍然有許多主流應用(Spring、Hibernate、Struts 等)能直接運行在 JDK 1.4 之上,或者繼續發布能運行在 JDK 1.4 上的版本。JDK 1.4 同樣發布了很多新的技術特性(正則表達式、異常鏈、NIO、日誌類、XML解析器 和 XSLT轉換器 等)。
2004-09-30:JDK 1.5 發布(從這個版本開始官方正式文檔宣傳上已經不再使用類似 JDK1.5的命名,只有在程序員內部使用的開發版本號,例如 java -version 的輸出,而公開版本號則改為 JDK 5),工程代號 Tiger(老虎)。從 JDK 1.2 以來,Java 在語法層面上的變換一直很小,而 JDK 1.5 在 Java 語法易用性上做出了非常大的改進。例如(自動裝箱、泛型、動態註釋、枚舉、可變長參數、foreach循環 等)語法特性都是在 JDK 1.5 中加入的。在虛擬機和 API 層面上,這個版本改進了 Java 的內存模型(Java Memory Model, JVM)、提供了 java.util.concurrent 並發包等。
2006-12-11:JDK 1.6 發布,工程代號 Mustang(野馬)。在這個版本中 Sun 終結了 JDK 1.2 開始已經有8年歷史的 J2EE、J2SE、J2ME 的命名方式,啟用 Java SE 6、Java EE 6、Java ME 6的命名方式。JDK 1.6 的改進包括:提供動態語言支持(通過內置 Mozilla JavaScript Rhino 引擎實現)、提供編譯 API 和微型 HTTP 服務器 API 等。同時,這個版本對 Java 虛擬機內部做了大量改進,包括 鎖與同步、垃圾回收、類加載 等方面的算法都有相當多的改動。
2006-11-13:JavaOne 大會上,Sun 公司宣布最終會將 Java 開源,並在隨後的一年多時間內,陸續將 JDK 的各個部分在 GPL v2(GNU General Public License v2)協議下 公開了源碼,並建立了 OpenJDK 組織對這些源碼進行獨立管理。除了極少量的產權代碼(Encumbered Code,這部分代碼大多是 Sun 本身也無權限進行開源處理的)外,OpenJDK 幾乎包括了 Sun JDK 的全部代碼,OpenJDK 的質量主管曾經表示,在 JDK 1.7 中,Sun JDK 和 OpenJDK 除了代碼文件頭的版權註釋之外,代碼基本上完全一樣,所以 OpenJDK 7 與 Sun JDK 1.7 本質上就是同一套代碼庫開發的產品。
JDK 1.6 發布以後,由於代碼復雜性的增加、JDK 開源、開發 JavaFX、經濟危機及 Sun 收購案等原因,Sun 在 JDK 發展以外的事情上耗費了很多資源,JDK 的更新並沒有再維持兩年發布一個版本的發展速度??。
2009-02-19:工程代號為 Dolphin(海豚)的 JDK 1.7 完成了其第一個裏程碑版本。根據 JDK 1.7 的功能規劃,一共設置了10個裏程碑。最後一個裏程碑版本原計劃與 2010 年 9 月 9 日技術,但由於各種原因,JDK 1.7 最終無法按計劃完成。
從 JDK 1.7 最開始的功能規劃來看,它本應是一個包含許多重要改進的 JDK 版本,其中 Lambda 項目(Lambda表達式、函數式編程)、Jigsaw項目(虛擬機模塊化支持)、動態語言支持、GarbageFirst收集器 和 Coin項目(語言細節進化)等子項目對於 Java 業界都會產生深遠的影響。在 JDK 1.7 開發期間,Sun 公司由於相繼在技術競爭和商業競爭中都陷入泥潭,公司的股票市值跌至僅有高峰時期的 3%(心疼),已無力推動 JDK 1.7 的研發工作按正常計劃進行。為了盡快結束 JDK 1.7 長期 ”跳票” 的問題,Oracle 公司收購 Sun 公司後不久便宣布將實行 “B計劃”,大幅裁剪了 JDK 1.7 預訂目標,以便保證 JDK 1.7 的正式版能夠與 2011年7月28日準時發布。”B計劃” 把不能按時完成的 Lambda 項目、Jigsaw 項目和 Coin 項目的部分改進延遲到 JDK 1.8之中。最終,JDK 1.7 的主要改進包括:提供新的 G1收集器、加強對非 Java 語言的調用支持、升級類加載架構 等。
2009-04-20:Oracle 公司宣布正式以74億美元的價格收購 Sun 公司,Java 商標從此正式歸 Oracle 所有( Java 語言本身並不屬於哪家公司所有,它由 JCP 組織進行管理,盡管 JCP 主要是由 Sun 公司或者說 Oracle 公司所領導的 )。由於此前 Oracle 公司已經收購了另外一家大型的中間件企業 BEA 公司,在完成對 Sun 公司的收購之後,Oracle 公司分別從 BEA 和 Sun 中取得了目前三大商業虛擬機其中兩個:JRockit 和 HotSpot,Oracle 公司宣布在未來的 1-2年的時間內,將把這兩個優秀的虛擬機相互取長補短,最終合二為一。
在 2011年的 JavaOne 大會上,Oracle 公司還提到了 JDK 1.9 的長遠規劃,希望未來的 Java 虛擬機能夠管理數以 GB 計的 Java 堆,能夠更高效地與本地代碼繼承,並且令 Java 虛擬機運行時盡可能少人工幹預,能夠自動調節。
1.4 - Java 虛擬機發展史
從 1996 年初 Sun 公司發布的 JDK 1.0 中所包含的 Sun Classic VM 到今天,曾經湧現、湮滅過許多經典或優秀或有特色的虛擬機實現,在這一節中我們一起來回顧一下 Java 虛擬機家族的發展軌跡和歷史變遷。
1.4.1 - Sun Classic / Exact VM
從今天的視角來看,Sun Classic VM 的技術可能很原始,這款虛擬機的使命也早已終結。但僅憑它 的頭銜,就足夠有讓歷史記住它的理由。
1996-01-23:Sun 公司發布 JDK 1.0,Java 語言首次擁有了商用的正式運行環境,這個 JDK 中所帶的虛擬機就是 Classic VM。這款虛擬機只能使用純解釋器方式來執行 Java 代碼,如果要使用 JIT 編譯器,就必須進行外掛。但是加入外掛了 JIT 編譯器,JIT 編譯器就完全接管了虛擬機的執行系統,解釋器便不再工作了。用戶在這款虛擬機上執行 java -version 命令,將會看到類似下面這行輸出
java version "1.2.2"
Classic VM (build JDK-1.2.2-001, green threads, sunwjit)
其中的 sunwjit 就是 Sun 提供的外掛編譯器,其他類似的外掛編譯器還有 Symantec JIT 和 shuJIT 等。由於 解釋器 和 編譯器 不能配合工作,這就意味著如果要使用編譯器執行,編譯器就不得不對每一個方法、每一行代碼都進行編譯,而無論他們執行的頻率是否具有編譯的價值。基於程序響應時間的壓力,這些編譯器根本不敢應用編譯耗時稍高的優化技術,因此這個階段的虛擬機即使使用了 JIT 編譯器輸出本地代碼,執行效率也和傳統的 C/C++ 程序有很大差距,Java 語言很慢 的形象就是在這時候開始在用戶心中樹立起來的。
Sun 的虛擬機團隊努力去解決 Classic VM 所面臨的各種問題,提升運行效率。在 JDK 1.2 時,曾在 Solaris 平臺上發布過一款名為 Exact VM 的虛擬機,它的執行系統已經具備現代高性能虛擬機的雛形:如 兩級即時編譯器、編譯器與解釋器混合工作模式 等。Exact VM 因它使用 準確式內存管理(Exact Memory Management)而得名,即虛擬機可以知道內存中某個位置的數據具體是什麽類型。例如內存中有一個 32 位的整數 123456,它到底是 reference 類型指向 123456 的內存地址還是一個數值為 123456 的整數,虛擬機將有能力分辨出來,這樣才能在 GC(垃圾收集)的時候準確判斷堆上的數據是否還可以被使用。由於使用了準確式內存管理,Exact VM 可以拋棄以前 Classic VM 基於 handler 的對象查找方式(原因是進行 GC 後對象將可能會被移動位置,如果將地址為 123456 的對象移動到 654321,在沒有明確信息表明內存中哪些數據是 reference 的前提下,虛擬機是不敢把內存中所有 123456 的值改為 654321 的,所以要使用句柄來保持 refrence 值的穩定),這樣每次定位對象都少了一次間接查找的開銷,提升執行性能。
雖然 Exact VM 的技術相對 Classic VM 來說先進了許多,但是在商業應用上只存在了很短暫的時間就被更為優秀的 HotSpot VM 所取代,甚至還沒有來得及發布 Windows 和 Linux 平臺下的商用版本。而 Classic VM 的生命周期則相對長了許多,它在 JDK 1.2 之前是 Sun JDK 中唯一的虛擬機,在 JDK 1.2時,它與 HotSpot VM 並存,但默認使用的是 Classic VM,而在 JDK 1.3 時,HotSopt VM 成為默認虛擬機,但 Classic VM 仍作為虛擬機的 “備用選擇” 發布,直到 JDK 1.4 的時候,Classic VM 才完全退出商用虛擬機的歷史舞臺,與 Exact VM 一起進入了 Sun Labs Research VM 中 。
1.4.2 - Sun HotSpot VM
提起 HotSpot VM,相信所有 Java 程序員都知道,它是 Sun JDK 和 OpenJDK 中所帶的虛擬機,也是目前 使用範圍最廣的 Java 虛擬機。但不一定所有人都知道的是,這個目前看來 ”血統純正” 的虛擬機在最初並非由 Sun 公司開發,而是一家名為 Longview Technologies 的小公司設計的;設置這個虛擬機最初並非是為 Java 語言而開發的,它來源於 Strongtalk VM,而這款虛擬機中相當多的技術又是來源於一款 Self 語言實現 “可能達到 C 語言 50% 以上的執行效率” 的目標而設計的虛擬機,Sun 公司註意到了這款虛擬機在 JIT 編譯上有許多優秀的理念和實際效果,在 1997 年收購了 Longview Technologies 公司,從而獲得了 HotSpot VM。
HotSpot VM 繼承了 Sun 之前兩款商用虛擬機的優點 => 準確式內存管理,也有許多自己新的技術優勢,如它名稱中的 HotSpot 指的就是它的 熱點代碼探測技術(其實兩個 VM 基本上是同時期的獨立產品,HotSpot 還稍早一些,HotSpot 一開始就是準確式 GC,而 Exact VM 中也有與之幾乎一樣的熱點探測。為了 Exact VM 和 HotSpot VM 哪個成為 Sun 主要支持的 VM 產品,在 Sun 公司內部還有過爭論,HotSpot 打敗 Exact 並不能算技術上的勝利),HotSpot VM 的熱點代碼探測能力可以通過執行計數器找出最具有編譯價值的代碼,然後通知 JIT 編譯器以方法為單位進行編譯。如果一個方法被頻繁調用,或方法中有效循環次數很多,將會被分別觸發 標準編譯 和 OSR(棧上替換) 編譯動作。通過編譯器與解釋器恰當地協同工作,可以在最優化的程序相應時間與最佳執行性能中取得平衡,而且無須等待本地代碼輸出才能執行程序,即時編譯的時間壓力也相對減小,這樣有助於引入更多的代碼優化技術,輸出質量更高的本地代碼。
在 2006 年的 JavaOne 大會上,Sun 公司宣布最終會把 Java 開源,並在隨後的一年,陸續將 JDK 的各個部分(其中當然也包括了 HotSpot VM)在 GPL 協議下公開了源碼,並在此基礎上建立了 OpenJDK。這樣,HotSpot VM 便成為了 Sun JDK 和 OpenJDK 兩個實現極度接近的 JDK 項目的共同虛擬機。
1.4.3 - Sun Mobile-Embedded VM / Meta-Circular VM
Sun 公司所研發的虛擬機可不僅有前面介紹的服務器、桌面領域的商用虛擬機,除此之外,Sun 公司面對 移動 和 嵌入式市場,也發布過虛擬機產品,另外還有一類虛擬機,在設計之初就沒報有商用目的,僅僅是用於研究、驗證某種技術和觀點,又或者是作為一些規範的標準實現。這些虛擬機對於大部分不從事相關領域開發的 Java 程序員來說可能比較陌生,Sun 公司發布的其他 Java 虛擬機有
KVM:K 是 Kilobyte 的意思,它強調簡單、輕量、高度可移植,但是運行速度比較慢。在 Android、iOS 等智能手機操作系統出現前曾經在手機平臺上得到非常廣泛的應用。
CDC/CLDC HotSpot Implementation:CDC/CLDC全稱是 Connected(Limited)Device Configuration,在 JSR-136、JSR-218 規範中進行定義,它希望在手機、電子書、PDA 等設備上建立統一的 Java 編程接口,而 CDC-HI VM 和 CLDC-HI VM 則是它們的一組參考實現。CDC/CLDC 是整個 JavaME 的重要支柱,但從目前 Android 和 iOS 二分天下的移動數字設備市場看來,在這個領域中,Sun 的虛擬機所面臨的局面遠不如服務器和桌面領域樂觀。
Squawk VM:Squawk VM 由 Sun 公司開發,運行於 Sun SPOT(Sun Small Programmable Object Technology,一種手持的 WiFi 設備),也曾經運用於 Java Card。這是一個 Java 代碼比重很高的嵌入式虛擬機實現,其中諸如類加載器、字節碼驗證器、垃圾回收器、解釋器、編譯器和線程調度都是 Java 語言本身完成的,僅僅靠 C 語言來編寫設備 I/O 和必要的本地代碼。
JavaInJava:JavaInJava 是 Sun 公司於 1997-1998 年間研發的一個實驗室性質的虛擬機,從名字就可以看出,它試圖以 Java 語言來實現 Java 語言本身的運行環境,即所謂的 “元循環”(Meta-Circular,是指使用語言自身來實現其運行環境)。它必須運行在另外一個宿主虛擬機之上,內部沒有 JIT 編譯器,代碼只能以解釋模式執行。在 20世紀末主流 Java 虛擬機都未能很好解決性能問題的時代,開發這種項目,其執行速度可想而知。
Maxine VM:Maxine VM 和上面的 JavaInJava 非常相似,它也是一個幾乎全部以 Java 代碼實現(只有用於啟動 JVM 的加載器使用 C 語言編寫)的元循環 Java 虛擬機。這個項目於 2005 年開始,到現在仍然在發展之中,比起 JavaInJava,Maxine VM 就顯得 “靠譜” 很多,它有先進的 JIT 編譯器和垃圾回收器(但沒有解釋器),可以在宿主模式或獨立模式下執行,其執行效率已經接近了 HotSpot Client VM 的水平。
1.4.4 BEA JRockit / IBM J9 VM
JRockit VM 曾經號稱 世界上速度最快的 Java 虛擬機(廣告詞,貌似 J9 VM 也這樣說過),它是 BEA 公司在 2002 年從 Appeal Virtual Machines 公司收購的虛擬機。BEA 公司將其發展為一款 專門為服務器硬件和服務器端應用場景高度優化的虛擬機,由於專註於服務器端應用,它可以不太關註程序啟動速度,因此 JRockit 內部不包含解析器實現,全部代碼都靠即時編譯器編譯後執行。除此之外,JRockit 的垃圾收集器和 MissionControl 服務套件等部分的實現,在眾多 Java 虛擬機中也一直處於領先水平。
IBM J9 VM 並不是 IBM 公司唯一個 Java 虛擬機,不過是目前其主力發展的 Java 虛擬機。IBM J9 VM 原本是內部開發代號,正式名稱是 “IBM Technology for Java Virtual Machine”,簡稱 IT4J,只是這個名字太拗口了一點,普及程度不如 J9。J9 VM 最初是由 IBM Ottawa 實驗室一個名為 SmallTalk 的虛擬機擴展而來,當時這個虛擬機有一個 bug 是由 8k 值定義錯誤引起的,工程師花了很長時間終於發現並解決了這個錯誤,此後這個版本的虛擬機就稱為 K8 了,後來擴展出支持 Java 的虛擬機就被稱為 J9 了。與 BEA JRockit 專註於服務器端應用不同,IBM J9 的市場定位與 Sun HotSpot 比較接近,它是一款設計上 從服務器端到桌面應用再到嵌入式都全面考慮的多用途虛擬機,J9 的開發目的是做為 IBM 公司各種 Java 產品的執行平臺,它的主要市場是和 IBM 產品(如 IBM WebSphere 等)搭配以及在 IBM AIX 和 z/OS 這些平臺上部署 Java 應用。
1.4.5 - Azul VM / BEA Liquid VM
Azul VM 是 Azul Systems 公司在 HotSpot 基礎上進行大量改進,運行於 Azul Systems 公司的專有硬件 Vega 系統上的 Java 虛擬機,每個 Azul VM 實例都可以管理至少數十個 CPU 和數百 GB 內存的硬件資源,並提供
在巨大內存範圍內實現可控的 GC 時間的垃圾收集器、為專有硬件優化的線程調度 等優秀特征。在 2010 年,Azul System 公司開始從硬件轉向軟件,發布了自己的 Zing JVM,可以在通用的 x86 平臺上提供接近於 Vega 系統的特性。
Liquid VM 即是現在的 JRockit VM 虛擬化版本,Liquid VM 不需要操作系統的支持,或者說它自己 本身實現了一個專有操作系統的必要功能,如文件系統、網絡操作等。由虛擬機越過通用操作系統直接控制硬件 可以獲得很多好處,如在線程調度時,不需要再進行內核態 / 用戶態的切換等,這樣可以最大限度地發揮硬件的功能,提升 Java 程序的執行性能。
1.4.6 - Apache Harmony / Google Android Dalvik VM
Apache Harmony 是一個 Apache 軟件基金會下以 Apache License 協議開源的實際兼容於 JDK 1.5 和 JDK 1.6 的 Java 程序運行平臺,這個介紹相當拗口。它包含自己的虛擬機和 Java 庫,用戶可以在上面運行 Eclipse、Tomcat、Maven 等常見的 Java 程序,但是它沒有通過 TCK 認證,所以我們不得不用那麽長一串拗口的語言來介紹它,而不能用一句 “Apache 的 JDK” 來說明。如果一個公司要宣布自己的運行平臺 “兼容於 Java 語言”,那就必須要通過 TCK(Technology Compatibility Kit)的兼容性測試。Apache 基金會曾經要求 Sun 公司提供 TCK 的使用授權,但是一直遭到拒絕,直到 Oracle 公司收購了 Sun 公司之後,雙方關系越鬧越僵,最終導致 Apache 憤然退出 JCP(Java Community Process) 組織,這是目前為止 Java 社區最嚴重的一次 “分裂”。
在 Sun 將 JDK 開源形成 OpenJDK 之後,Apache Harmony 開源的優勢被極大地削弱,甚至連 Harmony 項目的最大參與者 IBM 公司也宣布辭去 Harmony 項目管理主席的職位,並參與 OpenJDK 項目的開發。雖然 Harmony 沒有經歷過真正大規模的商業運作,但是它的許多代碼(基本上是 Java 庫部分的代碼)被吸納進 IBM 的 JDK7 實現及 Google Android SDK 之中,尤其是對 Android 的發展起到了很大的推動作用。
說到 Android,這個時下最熱門的移動數碼設備平臺在最近幾年間的發展過程中所取得的成果已經遠遠超越了 Java ME 在過去十多年所取得的成果,Android 讓 Java 語言真正走進了移動數碼設備領域,只是走的並非 Sun 公司原本想象的那一條路。
Dalvik VM 是 Android 平臺的核心組成部分之一,它的名字來源於冰島一個名為 Dalvik 的小漁村。Dalvik VM 並不是一個 Java 虛擬機,它沒有遵循 Java 虛擬機規範,不能直接執行 Java 的 Class 文件,使用的是 寄存器架構 而不是 JVM 中常見的 棧架構。但是它與 Java 又有著千絲萬縷的聯系,它執行的 dex(Dalvik Executable)文件可以通過 Class 文件轉化而來,使用 Java 語法編寫應用程序,可以直接使用大部分的 Java API 等。目前 Dalvik VM 隨著 Android 一起處於一個迅猛發展階段,在 Android 2.2 中已提供即時編譯器實現,在執行性能上有了很大的提高。
1.4.7 - Microsoft JVM 及其他
也許 Java 程序員聽起來可能會覺得驚訝,微軟公司曾經是 Java 技術的鐵桿支持者(也必須承認,與 Sun 公司爭奪 Java 控制權,令 Java 從跨平臺技術變為綁定在 Windows 上的技術是微軟公司的主要目的)。在 Java 語言誕生初期(1996年-1998年,以 JDK1.2 發布為界),它的主要應用之一是在瀏覽器中運行 Java Applets 程序,微軟公司為了在 IE3 中支持 Java Applets 應用而開發了自己的 Java 虛擬機,雖然這款虛擬機只有 Windows 平臺的版本,卻是當時 Windows 下性能最好的 Java 虛擬機,它在 1997年和1998年連續兩年獲得了《PC Magazine》雜誌的 “編輯選擇獎”。但好景不長,在 1997年10月,Sun 公司正式以侵犯商標、不正當競爭等罪名控告微軟公司,在隨後對微軟公司的壟斷調查之中,這款虛擬機也曾經作為證據之一被呈送法庭。這場官司的結果是微軟公司賠償 2000 萬美金給 Sun 公司(最終微軟公司因壟斷賠償給 Sun 公司的總金額高達 10 億美元),承諾終止其 Java 虛擬機的發展,並逐步在產品中移除 Java 虛擬機相關功能。具有諷刺意味的是,在最後 Windows XP SP3 中 Java 虛擬機被完全抹去的時候,Sun 公司卻又到處登報希望微軟公司不要這樣做。Windows XP 高級產品經理 Jim Cullinan 稱:”我們花了 3 年時間和 Sun 打官司,當時他們試圖阻止我們在 Windows 中支持 Java,現在我們這樣做了,可他們又在抱怨,這太具有諷刺意味了。”
如果當前 Sun 公司沒有起訴微軟公司,微軟公司繼續保持對 Java 技術的熱情,那 Java 的世界會變得怎麽樣呢?.NET 技術是否會發展起來?但歷史是沒有假設的。還有一些 Java 虛擬機是沒有介紹到的。
1.5 - 展望 Java 技術的未來
1.5.1 - 模塊化
模塊化是解決應用系統與技術平臺越來越服復雜、越來越龐大問題的一個重要途徑。無論是開發人員還是產品最終用戶,都不希望為了系統中一小塊的功能而不得不下載、安裝、部署及維護整套龐大的系統。站在整個軟件工業化的高度來看,模塊化是建立各種功能的標準件的前提。最近幾年 OSGi 技術的迅速發展、各個廠商在 JCP 中對模塊化規範的激烈鬥爭,都能充分說明模塊化技術的迫切和重要。
在未來的 Java 平臺中,很可能會對模塊化提出語法層面的支持。早在 2007 年,Sun 公司就提出過 JSR-277:Java 模塊系統(Java Module System),試圖建立 Java 平臺的模塊化標準,但受挫於以 IBM 公司為主導提交的 JSR-291:Java SE 動態組件支持(Dynamic Component Support for Java SE,這實際就是 OSGi R4.1)。由於模塊化規範主導權的重要性,Sun 公司不能接受一個無法由它控制的規範,Sun 公司再次提交了一個新的規範請求文檔 JSR-294:Java 編程語言中的改進模塊性支持(Improved Modularity Support in the Java Programming Language),盡管這個 JSR 仍然沒有通過,但是 Sun 公司已經獨立於 JCP 專家組在 OpenJDK 裏建立了一個名為 Jigsaw(拼圖)的子項目來推動這個規範在 Java 平臺中轉變為具體的實現。Java 模塊化之爭目前還沒有結束,OSGi 已經發布到 R5.0 版本,而 Jigsaw 從 Java 7 延遲至 Java 8,在 2012 年 7 月又不得不宣布推遲到 Java9 中發布,從這點看來,Sun 在這場戰爭中處於劣勢,但無論勝利者是哪一方,Java 模塊化已經成為一項無法阻擋的變革潮流。
1.5.2 - 混合語言
當單一的 Java 開發已經無法滿足當前軟件的復雜需求時,越來越多基於 Java 虛擬機的語言開發被應用到軟件項目中,Java 平臺上的多語言混合編程正成為為主流,每種語言都可以針對自己擅長的方面更好地解決問題。試想一下,在一個項目之中,並行處理用 Clojure 語言編寫,展示層使用 JRuby / Rails,中間層則是 Java,每個應用層都將使用不同的編程語言來完成,而且,接口對每一層的開發者都是透明的,各種語言之間的交互不存在任何困難,就像使用自己語言的原生 API 一樣方便,因為它們最終都運行在一個虛擬機之上。
在最近的幾年裏,Clojure、JRuby、Groovy 等新生語言的使用人數不斷增長,而運行在 Java 虛擬機(JVM)之上的語言數量也在迅速膨脹。通過特定領域的語言去解決特定領域的問題 是當前軟件開發應對日趨復雜的項目需求的一個方向。
Languages In The Java
除了催生出大量的新語言外,許多已經有很長歷史的程序語言也出現了基於 Java 虛擬機實現的版本,這樣使得混合編程對許多以前使用其他語言的 “老” 程序員也具備相當大的吸引力,軟件企業投入了大量資本的現有代碼資產也能很好地保護起來。
1.5.3 - 多核並行
如今,CPU 硬件的發展方向已經從高頻率轉變為 多核心,隨著多核時代的來臨,軟件開發越來越關註並行編程的領域。早在 JDK1.5 就已經引入 java.util.concurrent 包實現了一個粗粒度的並發框架。而 JDK1.7 中加入的 java.util.cuncurrent.forkjoin 包則是對這個框架的一次重要擴充。Fork / Join模式 是處理並行編程的一個經典方法。雖然不能解決所有的問題,但是在此模式的適用範圍之內,能夠輕松地利用多個 CPU 核心提供的計算資源來協作完成一個復雜的計算任務。通過利用 Fork / Join 模式,我們能夠更加順場地過渡到多核心時代。
Fork / Join 模式
在 Java 8 中,將會提供 Lambda 支持,這將會極大改善目前 Java 語言不適合 函數式編程 的現狀(目前 Java 語言使用函數式編程並不是不可以,只是會顯得很臃腫),函數式編程的一個重要優點就是這樣的程序天然地適合 並行運行,這對 Java 語言在多核時代繼續保持主流語言的地位有很大幫助。
另外,在並行計算中必須提及的還有 OpenJDK 的子項目 Sumatra,目前顯卡的算術運算能力、並行能力已經遠遠超過了 CPU,在圖形領域以發掘顯卡的潛力是近幾年計算機發展的方向之一,例如 C 語言的 CUDA。Sumatra 項目就是為 Java 提供使用 GPU(Graphics Processing Units)和 APU(Accelerated Processing Units) 運算能力的工具,以後它將會直接提供 Java 語言層面的 API,或者為 Lambda 和其他 JVM 語言提供底層的並行運算支持。
在 JDK 外圍,也出現了專為滿足並行計算需求的計算框架,如 Apache 的 Hadoop Map / Reduce,這是一個簡單易懂的並行框架,能夠運行在由上千個商用機器組成的大型集群上,並且能以一種可靠的容錯方式並行處理 TB 級別的數據集。另外,還出現了諸如 Scala、Clojure 及 Erlang 等天生就具備並行計算能力的語言。
1.5.4 - 進一步豐富語法
Java 5 曾經對 Java 語法進行了一次擴充,這次擴充加入了自動裝箱、泛型、動態註解、枚舉、可邊長參數、遍歷循環 等語法,使得 Java 語言的精確性和易用性有了很大的進步。在 Java 7(由於進度壓力,許多改進已推遲至 Java 8)中,對 Java 語言進行了另一次大規模的擴充。Sun(以被 Oracle 收購)專門為改進 Java 語法在 OpenJDK 中建立了 Coin 子項目來統一處理對 Java 語法的細節修改,如二進制數的原生支持、在 switch 語句中支持字符串、<>等操作符、異常處理的改進、簡化變長參數方法調用、面向資源的 try-catch-finally 語句等都是在 Coin 項目之中提交的內容。
除了 Coin 項目之外,在 JSR-355(Lambda Expressions for the Java TM Programming Language)中定義的 Lambda 表達式也將對 Java 的語法和語言習慣產生很大的影響,面向函數方式的編程可能會成為主流。
1.5.5 - 64位虛擬機
在幾年之前,主流的 CPU 就開始支持 64 位架構了。Java 虛擬機也是在很早之前就退出了支持 64 位系統的版本。但 Java 程序運行在 64 位虛擬機上需要付出比較大的額外代價:首先是 內存問題,由於 指針膨脹 和各種 數據類型對齊補白 的原因,運行於 64 位系統上的 Java 應用需要消耗更多的內存,通常要比 32 位系統額外增加 10%-30% 的內存消耗;其次,多個機構的測試結果顯示,64 位虛擬機的運行速度在各個測試項中幾乎全面落後於 32 位虛擬機,兩者大約有 15% 左右的性能差距。
但是在 Java EE 方面,企業級應用經常需要使用超過 4GB 的內存,對於 64 位虛擬機的需求是非常迫切的,但由於上述原因,許多企業應用仍然選擇使用虛擬集群等方式繼續在 32 位虛擬機中進行部署。Sun 也註意到了這些問題,並做出了一些改善,在 JDK 1.6 Update14 之後,提供了普通對象指針壓縮同能(-XX:+ UseCompressedOops,這個參數不建議顯示設置,建議維持默認由虛擬機的 Ergonomics 機制自動開啟),在執行代碼時,動態植入壓縮指令以節省內存消耗,但是開啟壓縮指針會增加執行代碼數量,因為所有在 Java 堆裏的、指向 Java 堆對象的指針都會被壓縮,這些指針的訪問就需要更多的代碼才可以實現,並且並不只是讀寫字段才受影響,在實例方法調用、子類型檢查等操作中也受影響,因為對象實例的引用也被壓縮了。隨著硬件的進一步發展,計算機終究會完全過渡到 64 位的時代,這是一件毫無疑問的事情,主流的虛擬機應用也終究會從 32 位發展至 64 位,而虛擬機對 64 位的支持也將會進一步完善。
原文鏈接:https://www.jianshu.com/p/4aa86f791beb
深入理解 Java 虛擬機——走近 Java