JVM之走進Java(一)

1、Java特點
不僅是一門編程語言,還是有一系列計算機軟件和規範形成的技術體系;除了是一門結構嚴謹、面向對象的編程語言之外:
(1)、跨平臺:一次編寫,到處運行,主要是java採用中間體(字節碼),而非是依賴平臺的機器碼,並且是在運行時編譯;
(2)、相對安全的內存管理和訪問機制,避免了絕大多數內存泄漏和指針越界問題;
(3)、實現了熱點代碼檢測和運行時編譯優化,可以使Java隨着運行時間的增加而獲得更高的性能;
(4)、一套完善的應用程序接口,還有無數來自商業機構和開源社區的第三方類庫。
2、Java技術體系
JDK:包含Java程序設計語言、Java虛擬機、Java API類庫
JRE:Java SE API(Java API子集)、Java虛擬機
Tip:JavaEE是對JavaSE的擴展,這些擴展包一般以javax.作爲包名,而java.作爲JavaSE核心包,歷史原因,一部分的擴展包進入了核心包,因此核心包中也包含了不少javax.*的包名。
3、Java的發展史
Oak(橡樹)作爲Java語言的前身,在1991年由James Gosling博士領導啓動,在1995年隨着互聯網的興起,Oak找到自己的定位並蛻變成Java語言,並且在SunWorld大會上Java1.0版本。(JDK1.0)第二年就提供一個純解釋執行的Java虛擬機Sun Classic VM。在1998年發佈的JDK1.2中第一次內置了JIT編譯器。2004年,發佈的JDK1.5(tiger)在語法應用上做了非常大的改進:自動裝箱、泛型、動態註解、枚舉、可變長參數、遍歷循環(foreach)等語法。
4、Java虛擬機的發展史
Sun公司從1996年發佈的JDK1.0提供了一個純解釋執行的虛擬機Sun Classic VM,由於相對於C/C++程序執行效率較低,於是在JDK1.2中,Solaris平臺上曾出現過一款名爲Exact VM的虛擬機,它已經具備現代高性能虛擬機的雛形:兩級即時編譯器、編譯器與解釋器混合工作模式、準確式內存管理(即JVM可以知道內存中某個位置的數據具體是什麼類型,比如一個數字123456是一個整型數字還是引用的地址),從而拋棄了以前的Classic VM的handler對象查詢方式。
但是Exact VM在商業上只存在了很短的時間就被更爲優秀的HotSpot VM所取代。HotSpot最初由一個小公司研發,最初也並非爲Java語言開發,它繼承了Sun之前兩款商用虛擬機(當然還有其他很多虛擬機:KVM、Squawk VM、JavaInJava等)的優點,也有自己新的技術優勢,比如熱點代碼探測技術,通過執行計數器找出最具有編譯價值的代碼,然後通知JIT編譯器以方法爲單位進行編譯,比如方法被頻繁調用或方法中有效循環次數很多,將會觸發標準編譯和OSR(棧上替換),即通過編譯器與解釋器協同工作,在最優化的程序響應時間與最佳執行性能中取得平衡,而無需等待本地代碼輸出才能執行程序。
最終經過Sun公司的內部討論決定採用HotSpot作爲Sun公司支持的VM產品。(並不算技術上的勝利)
2009年Oracle了收購Sun公司後加上以前收購的BEA公司,因此oracle擁有目前三大虛擬機的其中兩個:JRockit和HotSpot,並宣佈把兩個優秀的虛擬機取長補短合併爲一,且以HotSpot爲基礎。在2006年的時候Sun公司宣佈開源Java並建立了OpenJDK。
BEA JRockit:BEA公司開發一款專門爲服務器硬件和服務器端應用場景高度優化的虛擬機,由於專注於服務器端應用,因此不太注重程序啓動速度,因此JRockit VM內部不包含解析器實現,全部代碼都靠即時編譯器編譯後執行(即時編譯器因該是實時編譯源程序爲機器碼)。
IBM J9 VM:是IBM其中一款並且是主力發展的虛擬機,市場定位與Sun HotSpot接近,從服務端到桌面應用再到嵌入式都全面考慮的多用途虛擬機。
5、HotSpot虛擬機中的即時編譯器
HotSpot 虛擬機採用解釋器與編譯器並存的架構(不是所有的JVM都是這種架構),這也是主流商用虛擬機的架構。
解釋器:當程序需要快速啓動和執行的時候,解釋可以首先發揮作用,省去編譯的時間(這裏所說的編譯時複雜的優化等大範圍編譯過程,泛指相當於一部分(或全部)源碼編譯成機器碼然後執行),可以一邊解釋一邊執行(轉譯一行後就執行),但是在優化方面就比較劣勢,因此翻譯成的機器碼可能也比較耗時,即雖然節省了編譯的時間,但是卻要花費比較多的時間在執行指令上。
編譯器:在程序運行後,隨着時間的推移,編譯器逐漸發揮作用,把越來越多的代碼翻譯成本地代碼(也可能是一種其它的低級語言)之後,存在緩存裏,可以獲得更高的執行效率。(對比解釋器可能編譯後執行完當再次執行要重新編譯成機器碼)
因此:對於運行環境內存資源顯示較大(嵌入式系統)可以使用解釋執行節約內存。同時解釋器還可以組委編譯器激進優化的一個“逃生門”,就是編譯器根據概率選擇一些大多數時候都能提升運行速度的優化手段,當激進的假設不成立,如出現了加載了新類後類型繼承結構發生了變化、出現“罕見陷阱”時可以通過逆優化退回到解釋狀態繼續執行。

即時編譯器的作用:Java程序在進行解釋執行的時候,當虛擬機發現某個方法或代碼塊(循環體)運行特別頻繁時,會把這些代碼認定爲“”熱點代碼“(Hot Spot Code),爲了提高這些熱點代碼的執行效率,在運行時把熱點代碼以方法爲對象編譯成與本地平臺相關的機器碼(計算機指令使用特定平臺x86、x64、ARM),並進行各層次的優化,完成這個任務的編譯器稱爲即時編譯器(區別普通編譯器:運行前就把源碼編譯成特定平臺的機器碼,同時喪失了可移植性)
Java 執行引擎
這裏寫圖片描述
HotSpot VM內置了兩個即時編譯器,分別稱爲Client Compiler(C1)和Server Compiler(C2),1.7以及之前的版本中,默認採用解釋器與其中一個編譯器直接配合的方式工作,採用哪一個編譯器取決於虛擬機的運行模式,HotSpot會根據自身版本和宿主機器的硬件性能自動選擇運行模式,用戶也可以使用“-client”或“-server”去強制選擇。
HotSpot爲了在程序啓動響應速度與運行效率之間達到最佳平衡,在1.7的server模式虛擬機中啓用分層編譯的策略作爲默認編譯策略被開啓。
分層編譯根據編譯器編譯優化的規模與耗時,劃分不同的編譯層次,其中包括:
第0層,程序解釋執行,解釋器不開啓性能監控功能,可觸發第1層編譯
第1層,已稱爲C1編譯,將字節碼編譯爲本地代碼,進行簡單、可靠的優化,如有必要,將加入性能監控的邏輯。
第2層(及以上),也稱爲C2編譯,將字節碼轉換爲本地代碼,會進行一些耗時較長的優化,甚至會根據性能監控信息進行一些不可靠的激進優化。
分層編譯後,C1與C2同時工作,許多代碼可能會被編譯多次,用C1獲得更高的編譯速度,C2獲得更好的編譯質量。
6、HotSpot的熱點探測
熱點代碼主要有兩類:被多次調用的方法;被多次執行的循環體;但編譯執行對象都是方法。
熱點探測技術主要有兩種:
(1)、基於採樣的熱點探測:虛擬機週期性檢查各個線程的棧頂,棧頂經常出現的方法就是“熱點方法” 簡單 高效 還可以獲取方法的調用關係,但容易受到線程阻塞和外界因素的影響,很難準備探測方法的熱度。
(2)、基於計數器的熱點探測:虛擬機爲每個方法設置代碼塊建立計數器,統計執行次數,當超過閾值時,就認爲是“熱點方法” 。統計結果相對準確嚴謹,但不能知道方法調用關係。
HotSpot採用第二種方法,不過它爲每個方法採用兩種計數器:方法調用計數器和回邊計數器,每個計數器都有閾值 ,超過就出發JIT編譯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章