jvm執行引擎:後端編譯的運行過程和原理

1.概述

jvm將java字節碼文件轉換爲與當前平臺相關的二進制機器碼的過程,是由jvm中的執行引擎來處理,與javac將java文件轉化爲.class文件的前端編譯不同,javac並不處於jvm體系,且執行引擎是java虛擬機核心組成部分之一,它的任務是將字節碼指令解釋/編譯爲對應平臺上的機器指令
在這裏插入圖片描述

在執行引擎工作過程中,它需要執行的字節碼指令是依賴於pc寄存器的,這一過程可以去看
Java虛擬機-pc寄存器執行過程理解

2.解釋器和編譯器概述

字節碼文件被加載到內存中後就等待被執行了,執行這些代碼需要依靠執行引擎,在目前主流的比如HotSpot,OpenJ9虛擬機中,執行引擎中有解釋器(Interpreter)即時編譯器(Just In Time,JIT)兩種方式來將字節碼文件轉化爲機器碼指令,解釋器會對字節碼採用逐行解釋方式執行,將字節碼文件中的內容轉化爲對應平臺的機器碼,而編譯器是直接將用的比較多的代碼編譯成本地代碼,生成緩存(cached)放在方法區中,這樣可以減少解釋器的中間消耗,獲得更高的執行效率
在這裏插入圖片描述

3.java是半編譯半解釋型語言

java在JDK1.0時代,程序都是通過解釋器來執行的,所以java在最初的時候運行速度是不如C/C++的,後來虛擬機發展了即時編譯器可以直接生成本地緩存,java程序的執行效率得到大大提升,現在的jvm在執行java代碼的時候既可以通過解釋器執行,也可以通過即時編譯器執行,,但大多數情況下將兩者結合使用,所以將Java稱爲半編譯半解釋型語言

3.1關於java跨平臺性的補充

java的跨平臺性主要指的時class文件的跨平臺,java文件和C/C++不同,可以做到一處編譯,到處運行主要得益於jvm,作爲虛擬機,比如CentOs,我們可以只用下載一個鏡像系統就可以使用一個截然不同的操作系統,不受制於硬件的約束,jvm也是如此,只需要與之對應平臺的操作系統就可以執行class文件,而class文件是一種中間狀態的二進制文件,需要轉義後才能稱爲機器碼,類似C++的源文件,經編譯爲彙編後在轉爲機器碼
在這裏插入圖片描述

4.HotSpot中的解釋器和JIT編譯器

java一共有兩種解釋器:古老的字節碼解釋器和現在普遍使用的模板解釋器字節碼解釋器逐行執行字節碼,效率非常低下,模板解釋器顧名思義,套模板,和我們寫作文時套用模板一樣,可以提高解釋器的性能,雖然性能有所提高,但效率仍然比不C/C++,運用解釋器執行的還有Python,Ruby等高級語言,爲了解決這個問題,JVM平臺支持了一種即時編譯的技術,將越來越多的代碼編譯成本地代碼緩存,避免被解釋執行,下一次用的時候就可以直接執行編譯好的機器碼,效率很高
在這裏插入圖片描述
那麼既然編譯器效率如此高,爲什麼HotSpot仍然要使用解釋器和即時編譯器並存的架構?
JRockit虛擬機就沒有解釋器,目前已經不再發展了,我們需要知道,這兩種架構各有優缺點

  • 在程序啓動時,解釋器可以立馬發揮作用,省去編譯時間,立即執行,而編譯器要先把代碼編譯爲本地代碼,要一定的時間,但編譯完成後效率很高

HotSpot虛擬機的方案時:當程序需要迅速啓動並執行時,解釋器首先發揮作用,一旦程序啓動,隨着時間推移,編譯器發揮作用,減少解釋器的中間損耗,獲得更高的執行效率,並且解釋器可以充當編譯器在激進優化不成功的時候的逃生門

5.判斷是否使用JIT編譯器

前面我們說過編譯器的優點,那麼什麼情況下使用編譯器呢?當虛擬機發現某個方法或代碼塊用的特別頻繁,就會把這些代碼認定爲熱點代碼,爲了優化熱點代碼的執行效率,就可以使用編譯器,這裏的熱點代碼主要有兩類:

  • 被多次調用的方法
  • 被多次執行的循環體

熱點代碼經過JIT編譯器編譯爲本地機器指令的編譯方式被稱爲棧上替換(OSR,On Stack Replacement)編譯,一個方法或循環體究竟需要被調用幾次,執行多少次循環才能被當作熱點代碼? 目前HotSpot虛擬機採用的熱點探測技術是基於計數器的熱點探測

5.1方法調用計數器

這個計數器就是用於統計方法被調用的次數,它的閾值在Client模式下是1500次,在Server模式下是10000次,我們常用的JDK都是Server模式,
在這裏插入圖片描述
當一個方法被調用時,回先檢查該方法是否存在被JIT編譯過的版本,如果存在就會使用編譯後的本地代碼來執行,如果不存在則將此方法的閾值加1,然後判斷是否達到閾值,如果達到,則會提交一個該方法的代碼編譯請求,具體過程如下:
在這裏插入圖片描述

5.2熱度衰減

在這種情況下,如果不做任何處理,那麼每一個方法的調用都會使得其閾值不斷增加,最終被編譯,JVM採用的是一段時間內方法被調用的次數,當超過一定時間限度,如果這個方法的調用次數未達到閾值,次數則會減少一半,這個過程被稱爲熱度衰減,這段時間被稱爲半衰週期,我們可以通過設置參數來調整絆摔週期:-XX:CounterHalfLifeTime設置,單位是S,
-XX:-UseCounterDeacy來關閉熱度衰減

5.3設置程序執行方式

  • -Xint:完全採用解釋器模式
  • -Xcomp:完全採用編譯器模式,如果編譯出現問題,解釋器會介入
  • -Xmixed:採用解釋器+編譯器混合模式

在這裏插入圖片描述

6.JIT編譯器分類

HotSpot虛擬機不光有兩種架構的執行引擎,對JIT編譯器又內嵌了兩種編譯器分別爲Client CompilerServer Compiler,簡稱爲C1和C2編譯器,可通過如下命令選擇具體哪一種編譯器

  • -client:運行在client模式下,使用c1編譯器,c1編譯器會對字節碼文件進行簡單和可靠的優化,耗時短,達到更快的編譯速度
  • -server:運行在server模式下,使用c2編譯器,c2進行耗時較長的優化,以及激進優化,但代碼執行效率更高

說明:當JDK是64位版本,默認是server模式,C2編譯器啓動時長比C1編譯器慢,但系統穩定後,C2編譯器執行速度遠高於C1編譯器

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