深入理解java虛擬機

姓名:周君會? ? ? ? ? ? 學號:17011210526

轉載自:

http://www.lxweimin.com/p/f66ae2f977c6

【嵌牛導讀】:如今java的應用越來越廣泛,java可以通過編寫程序來開發app。

【嵌牛鼻子】:越來越多的人都在學習java,因其功能的強大受到越來越多學者的歡迎。

【嵌牛提問】:但是你真的理解java虛擬機嗎?讓我們來深入理解java虛擬機。

【嵌牛正文】:


世界上并沒有完美的程序,但我們并不因此而沮喪,因為寫程序本來就是一個不斷追求完美的過程。

1.1 概述

Java不僅僅是一門編程語言,還是一個由一系列計算機軟件和規范形成的技術體系,這個技術體系提供了完整的用于軟件開發和跨平臺部署的支持環境,并廣泛應用于嵌入式系統、移動終端、企業服務器、大型機等各種場合,如圖1-1所示。時至今日,Java技術體系已經吸引了900多萬軟件開發者,這是全球最大的軟件開發團隊。使用Java的設備多達幾十億臺,其中包括11億多臺個人計算機、30億部移動電話及其他手持設備、數量眾多的智能卡,以及大量機頂盒、導航系統和其他設備。

圖片發自簡書App

圖1-1 Java技術的廣泛應用

Java能獲得如此廣泛的認可,除了它擁有一門結構嚴謹、面向對象的編程語言之外,還有許多不可忽視的優點:它擺脫了硬件平臺的束縛,實現了“一次編寫,到處運行”的理想;它提供了一個相對安全的內存管理和訪問機制,避免了絕大部分的內存泄露和指針越界問題;它實現了熱點代碼檢測和運行時編譯及優化,這使得Java應用能隨著運行時間的增加而獲得更高的性能;它有一套完善的應用程序接口,還有無數來自商業機構和開源社區的第三方類庫來幫助它實現各種各樣的功能……Java所帶來的這些好處使程序的開發效率得到了很大的提升。作為一名Java程序員,在編寫程序時除了盡情發揮Java的各種優勢外,還應該去了解和思考一下Java技術體系中這些技術特性是如何實現的。認識這些技術運作的本質,是自己思考“程序這樣寫好不好”的基礎和前提。當我們在使用一種技術時,如果不再依賴書本和他人就能得到這些問題的答案,那才算上升到了“不惑”的境界。

本書將與讀者一起分析Java技術中最重要的那些特性的實現原理。在本章中,我們將重點介紹Java技術體系內容以及Java的歷史、現在和未來的發展趨勢。

1.2 Java技術體系

從廣義上講,Clojure、JRuby、Groovy等運行于Java虛擬機上的語言及其相關的程序都屬于Java技術體系中的一員。如果僅從傳統意義上來看,Sun官方所定義的Java技術體系包括以下幾個組成部分:

Java程序設計語言

各種硬件平臺上的Java虛擬機

Class文件格式

Java API類庫

來自商業機構和開源社區的第三方Java類庫

我們可以把Java程序設計語言、Java虛擬機、Java API類庫這三部分統稱為JDK(Java Development Kit),JDK是用于支持Java程序開發的最小環境,在后面的內容中,為了講解方便,有一些地方會以JDK來代替整個Java技術體系。另外,可以把Java API類庫中的Java SE API子集 和Java虛擬機這兩部分統稱為JRE(Java Runtime Environment),JRE是支持Java程序運行的標準環境。圖1-2展示了Java技術體系所包含的內容,以及JDK和JRE所涵蓋的范圍。

圖片發自簡書App

圖1-2 Java技術體系所包含的內容

以上是根據各個組成部分的功能來進行劃分的,如果按照技術所服務的領域來劃分,或者說按照Java技術關注的重點業務領域來劃分,Java技術體系可以分為4個平臺,分別為:

Java Card:支持一些Java小程序(Applets)運行在小內存設備(如智能卡)上的平臺。

Java ME(Micro Edition):支持Java程序運行在移動終端(手機、PDA)上的平臺,對Java API有所精簡,并加入了針對移動終端的支持,這個版本以前稱為J2ME。

Java SE(Standard Edition):支持面向桌面級應用(如Windows下的應用程序)的Java平臺,提供了完整的Java核心API,這個版本以前稱為J2SE。

Java EE(Enterprise Edition):支持使用多層架構的企業應用(如ERP、CRM應用)的Java平臺,除了提供Java SE API外,還對其做了大量的擴并提供了相關的部署支持,這個版本以前稱為J2EE。

1.3 Java發展史

從第一個Java版本誕生到現在已經有18年的時間了。滄海桑田一瞬間,轉眼18年過去了,在圖1-3所展示的時間線中,我們看到JDK已經發展到了1.7版。在這18年里還誕生了無數和Java相關的產品、技術和標準。現在讓我們走入時間隧道,從孕育Java語言的時代開始,再來回顧一下Java的發展軌跡和歷史變遷。

圖片發自簡書App

圖片發自簡書App

圖片發自簡書App

圖1-3 Java技術發展的時間線

1991年4月,由James Gosling博士領導的綠色計劃(Green Project)開始啟動,此計劃的目的是開發一種能夠在各種消費性電子產品(如機頂盒、冰箱、收音機等)上運行的程序架構。這個計劃的產品就是Java語言的前身:Oak(橡樹)。Oak當時在消費品市場上并不算成功,但隨著1995年互聯網潮流的興起,Oak迅速找到了最適合自己發展的市場定位并蛻變成為Java語言。

1995年5月23日,Oak語言改名為Java,并且在SunWorld大會上正式發布Java 1.0版本。Java語言第一次提出了“Write Once,Run Anywhere”的口號。

1996年1月23日,JDK 1.0發布,Java語言有了第一個正式版本的運行環境。JDK 1.0提供了一個純解釋執行的Java虛擬機實現(Sun Classic VM)。JDK 1.0版本的代表技術包括:Java虛擬機、Applet、AWT等。

1996年4月,10個最主要的操作系統供應商申明將在其產品中嵌入Java技術。同年9月,已有大約8.3萬個網頁應用了Java技術來制作。在1996年5月底,Sun公司于美國舊金山舉行了首屆JavaOne大會,從此JavaOne成為全世界數百萬Java語言開發者每年一度的技術盛會。

1997年2月19日,Sun公司發布了JDK 1.1,Java技術的一些最基礎的支撐點(如JDBC等)都是在JDK 1.1版本中發布的,JDK 1.1版的技術代表有:JAR文件格式、JDBC、JavaBeans、RMI。Java語法也有了一定的發展,如內部類(Inner Class)和反射(Reflection)都是在這個時候出現的。

直到1999年4月8日,JDK 1.1一共發布了1.1.0~1.1.8九個版本。從1.1.4之后,每個JDK版本都有一個自己的名字(工程代號),分別為:JDK 1.1.4 - Sparkler(寶石)、JDK 1.1.5-Pumpkin(南瓜)、JDK 1.1.6-Abigail(阿比蓋爾,女子名)、JDK 1.1.7-Brutus(布魯圖,古羅馬政治家和將軍)和JDK 1.1.8–Chelsea(切爾西,城市名)。

1998年12月4日,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)編譯器(JDK 1.2中曾并存過3個虛擬機,Classic VM、HotSpot VM和Exact VM,其中Exact VM只在Solaris平臺出現過;后面兩個虛擬機都是內置JIT編譯器的,而之前版本所帶的Classic VM只能以外掛的形式使用JIT編譯器)。在語言和API級別上,Java添加了strictfp關鍵字與現在Java編碼之中極為常用的一系列Collections集合類。在1999年3月和7月,分別有JDK1.2.1和JDK 1.2.2兩個小版本發布。

1999年4月27日,HotSpot虛擬機發布,HotSpot最初由一家名為“Longview Technologies”的小公司開發,因為HotSpot的優異表現,這家公司在1997年被Sun公司收購了。HotSpot虛擬機發布時是作為JDK 1.2的附加程序提供的,后來它成為了JDK 1.3及之后所有版本的Sun JDK的默認虛擬機。

2000年5月8日,工程代號為Kestrel(美洲紅隼)的JDK 1.3發布,JDK 1.3相對于JDK 1.2的改進主要表現在一些類庫上(如數學運算和新的Timer API等),JNDI服務從JDK 1.3開始被作為一項平臺級服務提供(以前JNDI僅僅是一項擴展),使用CORBA IIOP來實現RMI的通信協議,等等。這個版本還對Java 2D做了很多改進,提供了大量新的Java2D API,并且新添加了JavaSound類庫。JDK 1.3有1個修正版本JDK 1.3.1,工程代號為Ladybird(瓢蟲),于2001年5月17日發布。

自從JDK 1.3開始,Sun維持了一個習慣:大約每隔兩年發布一個JDK的主版本,以動物命名,期間發布的各個修正版本則以昆蟲作為工程名稱。

2002年2月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轉換器等。JDK 1.4有兩個后續修正版:2002年9月16日發布的工程代號為Grasshopper(蚱蜢)的JDK 1.4.1與2003年6月26日發布的工程代號為Mantis(螳螂)的JDK 1.4.2。

2002年前后還發生了一件與Java沒有直接關系,但事實上對Java的發展進程影響很大的事件,那就是微軟公司的.NET Framework發布了。這個無論是技術實現上還是目標用戶上都與Java有很多相近之處的技術平臺給Java帶來了很多討論、比較和競爭,.NET平臺和Java平臺之間聲勢浩大的孰優孰劣的論戰到目前為止都在繼續。

2004年9月30日,JDK 1.5發布,工程代號Tiger(老虎)。從JDK 1.2以來,Java在語法層面上的變換一直很小,而JDK 1.5在Java語法易用性上做出了非常大的改進。例如,自動裝箱、泛型、動態注解、枚舉、可變長參數、遍歷循環(foreach循環)等語法特性都是在JDK 1.5中加入的。在虛擬機和API層面上,這個版本改進了Java的內存模型(Java Memory Model,JMM)、提供了java.util.concurrent并發包等。另外,JDK 1.5是官方聲明可以支持Windows 9x平臺的最后一個JDK版本。

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的更新沒有再維持兩年發布一個主版本的發展速度。JDK 1.6到目前為止一共發布了37個Update版本,最新的版本為Java SE 6 Update 37,于2012年10月16日發布。

2009年2月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收集器(G1在發布時依然處于Experimental狀態,直至2012年4月的Update 4中才正式“轉正”)、加強對非Java語言的調用支持(JSR-292,這項特性到目前為止依然沒有完全實現定型)、升級類加載架構等。

到目前為止,JDK 1.7已經發布了9個Update版本,最新的Java SE 7 Update 9于2012年10月16日發布。從Java SE 7 Update 4起,Oracle開始支持Mac OS X操作系統,并在Update 6中達到完全支持的程度,同時,在Update 6中還對ARM指令集架構提供了支持。至此,官方提供的JDK可以運行于Windows(不含Windows 9x)、Linux、Solaris和Mac OS平臺上,支持ARM、x86、x64和Sparc指令集架構類型。

2009年4月20日,Oracle公司宣布正式以74億美元的價格收購Sun公司,Java商標從此正式歸Oracle所有(Java語言本身并不屬于哪間公司所有,它由JCP組織進行管理,盡管JCP主要是由Sun公司或者說Oracle公司所領導的)。由于此前Oracle公司已經收購了另外一家大型的中間件企業BEA公司,在完成對Sun公司的收購之后,Oracle公司分別從BEA和Sun中取得了目前三大商業虛擬機的其中兩個:JRockit和HotSpot,Oracle公司宣布在未來1~2年的時間內,將把這兩個優秀的虛擬機互相取長補短,最終合二為一。可以預見在不久的將來,Java虛擬機技術將會產生相當巨大的變化。

根據Oracle官方提供的信息,JDK 1.8的第一個正式版本將于2013年9月發布,JDK 1.8將會提供在JDK 1.7中規劃過,但最終未能在JDK 1.7中發布的特性,即Lambda表達式、Jigsaw(很不幸,隨后Oracle公司又宣布Jigsaw在JDK 1.8中依然無法完成,需要延至JDK 1.9)和JDK 1.7中未實現的一部分Coin等。

在2011年的JavaOne大會上,Oracle公司還提到了JDK 1.9的長遠規劃,希望未來的Java虛擬機能夠管理數以GB計的Java堆,能夠更高效地與本地代碼集成,并且令Java虛擬機運行時盡可能少人工干預,能夠自動調節。

1.4 Java虛擬機發展史

上一節我們從整個Java技術的角度觀察了Java技術的發展,許多Java程序員都會潛意識地把它與Sun公司的HotSpot虛擬機等同看待,也許還有一些程序員會注意到BEA JRockit和IBM J9,但對JVM的認識不僅僅只有這些。

從1996年初Sun公司發布的JDK 1.0中所包含的Sun Classic VM到今天,曾經涌現、湮滅過許多或經典或優秀或有特色的虛擬機實現,在這一節中,我們先暫且把代碼與技術放下,一起來回顧一下Java虛擬機家族的發展軌跡和歷史變遷。

1.4.1 Sun Classic/Exact VM

以今天的視角來看,Sun Classic VM的技術可能很原始,這款虛擬機的使命也早已終結。但僅憑它“世界上第一款商用Java虛擬機”的頭銜,就足夠有讓歷史記住它的理由。

1996年1月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,也可以叫Non-Conservative/Accurate Memory Management)而得名,即虛擬機可以知道內存中某個位置的數據具體是什么類型。譬如內存中有一個32位的整數123456,它到底是一個reference類型指向123456的內存地址還是一個數值為123456的整數,虛擬機將有能力分辨出來,這樣才能在GC(垃圾收集)的時候準確判斷堆上的數據是否還可能被使用。由于使用了準確式內存管理,Exact VM可以拋棄以前Classic VM基于handler的對象查找方式(原因是進行GC后對象將可能會被移動位置,如果將地址為123456的對象移動到654321,在沒有明確信息表明內存中哪些數據是reference的前提下,虛擬機是不敢把內存中所有為123456的值改成654321的,所以要使用句柄來保持reference值的穩定),這樣每次定位對象都少了一次間接查找的開銷,提升執行性能。

雖然Exact VM的技術相對Classic VM來說先進了許多,但是在商業應用上只存在了很短暫的時間就被更為優秀的HotSpot VM所取代,甚至還沒有來得及發布Windows和Linux平臺下的商用版本。而Classic VM的生命周期則相對長了許多,它在JDK 1.2之前是Sun JDK中唯一的虛擬機,在JDK 1.2時,它與HotSpot VM并存,但默認使用的是Classic VM (用戶可用java-hotspot參數切換至HotSpot VM),而在JDK 1.3時,HotSpot VM成為默認虛擬機,但Classic VM仍作為虛擬機的“備用選擇”發布(使用java-classic參數切換),直到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之中也有與HotSpot幾乎一樣的熱點探測。為了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項目的共同虛擬機。

在2008年和2009年,Oracle公司分別收購了BEA公司和Sun公司,這樣Oracle就同時擁有了兩款優秀的Java虛擬機:JRockit VM和HotSpot VM。Oracle公司宣布在不久的將來(大約應在發布JDK 8的時候)會完成這兩款虛擬機的整合工作,使之優勢互補。整合的方式大致上是在HotSpot的基礎上,移植JRockit的優秀特性,譬如使用JRockit的垃圾回收器與MissionControl服務,使用HotSpot的JIT編譯器與混合的運行時系統。

1.4.3 Sun Mobile-Embedded VM/Meta-Circular VM

Sun公司所研發的虛擬機可不僅有前面介紹的服務器、桌面領域的商用虛擬機,除此之外,Sun公司面對移動和嵌入式市場,也發布過虛擬機產品,另外還有一類虛擬機,在設計之初就沒抱有商用的目的,僅僅是用于研究、驗證某種技術和觀點,又或者是作為一些規范的標準實現。這些虛擬機對于大部分不從事相關領域開發的Java程序員來說可能比較陌生。Sun公司發布的其他Java虛擬機有:

(1)KVM

KVM中的K是“Kilobyte”的意思,它強調簡單、輕量、高度可移植,但是運行速度比較慢。在Android、iOS等智能手機操作系統出現前曾經在手機平臺上得到非常廣泛的應用。

(2)CDC/CLDC HotSpot Implementation

CDC/CLDC全稱是Connected(Limited)Device Configuration,在JSR-139/JSR-218規范中進行定義,它希望在手機、電子書、PDA等設備上建立統一的Java編程接口,而CDC-HI VM和CLDC-HI VM則是它們的一組參考實現。CDC/CLDC是整個Java ME的重要支柱,但從目前Android和iOS二分天下的移動數字設備市場看來,在這個領域中,Sun的虛擬機所面臨的局面遠不如服務器和桌面領域樂觀(3)Squawk VM

Squawk VM由Sun公司開發,運行于Sun SPOT(Sun Small Programmable Object Technology,一種手持的WiFi設備),也曾經運用于Java Card。這是一個Java代碼比重很高的嵌入式虛擬機實現,其中諸如類加載器、字節碼驗證器、垃圾收集器、解釋器、編譯器和線程調度都是Java語言本身完成的,僅僅靠C語言來編寫設備I/O和必要的本地代碼。

(4)JavaInJava

JavaInJava是Sun公司于1997年~1998年間研發的一個實驗室性質的虛擬機,從名字就可以看出,它試圖以Java語言來實現Java語言本身的運行環境,既所謂的“元循環”(Meta-Circular,是指使用語言自身來實現其運行環境)。它必須運行在另外一個宿主虛擬機之上,內部沒有JIT編譯器,代碼只能以解釋模式執行。在20世紀末主流Java虛擬機都未能很好解決性能問題的時代,開發這種項目,其執行速度可想而知。

(5)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

前面介紹了Sun公司的各種虛擬機,除了Sun公司以外,其他組織、公司也研發過不少虛擬機實現,其中規模最大、最著名的就是BEA和IBM公司了。

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

我們平時所提及的“高性能Java虛擬機”一般是指HotSpot、JRockit、J9這類在通用平臺上運行的商用虛擬機,但其實Azul VM和BEA Liquid VM這類特定硬件平臺專有的虛擬機才是“高性能”的武器。

Azul VM是Azul Systems公司在HotSpot基礎上進行大量改進,運行于Azul Systems公司的專有硬件Vega系統上的Java虛擬機,每個Azul VM實例都可以管理至少數十個CPU和數百GB內存的硬件資源,并提供在巨大內存范圍內實現可控的GC時間的垃圾收集器、為專有硬件優化的線程調度等優秀特性。

2010年,Azul Systems公司開始從硬件轉向軟件,發布了自己的Zing JVM,可以在通用x86平臺上提供接近于Vega系統的特性。

Liquid VM即是現在的JRockit VE(Virtual Edition),它是BEA公司開發的,可以直接運行在自家Hypervisor系統上的JRockit VM的虛擬化版本,Liquid VM不需要操作系統的支持,或者說它自己本身實現了一個專用操作系統的必要功能,如文件系統、網絡支持等。由虛擬機越過通用操作系統直接控制硬件可以獲得很多好處,如在線程調度時,不需要再進行內核態/用戶態的切換等,這樣可以最大限度地發揮硬件的能力,提升Java程序的執行性能。

1.4.6 Apache Harmony/Google Android Dalvik VM

這節介紹的Harmony VM和Dalvik VM只能稱做“虛擬機”,而不能稱做“Java虛擬機”,但是這兩款虛擬機(以及所代表的技術體系)對最近幾年的Java世界產生了非常大的影響和挑戰,甚至有些悲觀的評論家認為成熟的Java生態系統有崩潰的可能。

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的JDK 7實現及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虛擬機外,還有許多虛擬機是不為人知的或者曾經“絢麗”過但最終湮滅的。我們以其中微軟公司的JVM為例來介紹一下。

也許Java程序員聽起來可能會覺得驚訝,微軟公司曾經是Java技術的鐵桿支持者(也必須承認,與Sun公司爭奪Java的控制權,令Java從跨平臺技術變為綁定在Windows上的技術是微軟公司的主要目的)。在Java語言誕生的初期(1996年~1998年,以JDK 1.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虛擬機還有(當然,應該還有很多筆者所不知道的):

JamVM。

cacaovm。

SableVM。

Kaffe。

Jelatine JVM。

NanoVM。

MRP。

Moxie JVM。

Jikes RVM。

1.5 展望Java技術的未來

在2005年,Java語言誕生10周年的SunOne技術大會上,Java語言之父James Gosling做了一場題為“Java技術下一個十年”的演講。筆者不具備James Gosling博士那樣高屋建瓴的視角,這里僅從Java平臺中幾個新生的但已經開始展現出蓬勃之勢的技術發展點來看一下后續1~2個JDK版本內的一些很有希望的技術重點。

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,這實際就是OSGiR4.1)。由于模塊化規范主導權的重要性,Sun公司不能接受一個無法由它控制的規范,在整個Java SE 6期間都拒絕把任何模塊化技術內置到JDK之中。在Java SE 7發展初期,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月又不得不宣布推遲到Java 9中發布,從這點看來,Sun在這場戰爭中處于劣勢,但無論勝利者是哪一方,Java模塊化已經成為一項無法阻擋的變革潮流。

1.5.2 混合語言

當單一的Java開發已經無法滿足當前軟件的復雜需求時,越來越多基于Java虛擬機的語言開發被應用到軟件項目中,Java平臺上的多語言混合編程正成為主流,每種語言都可以針對自己擅長的方面更好地解決問題。試想一下,在一個項目之中,并行處理用Clojure語言編寫,展示層使用JRuby/Rails,中間層則是Java,每個應用層都將使用不同的編程語言來完成,而且,接口對每一層的開發者都是透明的,各種語言之間的交互不存在任何困難,就像使用自己語言的原生API一樣方便,因為它們最終都運行在一個虛擬機之上。

在最近的幾年里,Clojure、JRuby、

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 從今天開始讀《深入理解 Java 虛擬機》一書,并開設了同名專題 深入理解 Java 虛擬機。計劃在 2 周內將全...
    SawyerZh閱讀 10,265評論 17 215
  • 《深入理解Java虛擬機》筆記_第一遍 先取看完這本書(JVM)后必須掌握的部分。 第一部分 走近 Java 從傳...
    xiaogmail閱讀 5,175評論 1 34
  • 居然又改了平臺,開始簡書上寫日記了。 最近確實有些魔怔了。 見鬼的人品和見鬼的沖動。 本來以為再也見不到的某人突然...
    一只鐵匠閱讀 311評論 0 0
  • 常常會看見這樣的一句話,看過的書不管你記住還是忘記長時間的積累都會慢慢的沁在你的骨子里,當時的自己會有疑問,為什么...
    崴崴閱讀 200評論 0 1
  • 無論如何,我都覺得,今天晚上屬于英雄聯盟的盛會,是一件美好的事情。 我不玩兒游戲,但今天朋友圈被一群80、90后的...
    滿夏summer閱讀 267評論 0 0