天天看點

關于HotSpot VM以及Java語言的動态編譯 你可能想知道這些

SUN/Oracle JDK中使用的JVM是HotSpot VM, 本篇介紹HotSpot VM的一些概念和容易被混淆的細節: 先對HotSpot VM的曆史、特性進行介紹, 然後引出Java是一種解釋型語言, HotSpot通過對常用的部分代碼編譯為本地(native)代碼, 顯著提高性能. 能力有限, 難免有疏漏, 來留言區交流吧😁

目錄

  • 1 HotSpot VM的曆史
  • 2 HotSpot VM 概述
    • 2.1 編譯器
    • 2.2 解釋器
    • 2.3 解釋型語言 VS 編譯型語言
  • 3 動态編譯
    • 3.1 什麼是動态編譯
    • 3.2 HotSpot VM對位元組碼的處理方式
    • 3.3 為什麼不靜态編譯
  • 參考資料
  • 版權聲明

SUN/Oracle JDK中使用的JVM是HotSpot VM.

SUN JDK從1.3.1版本開始采用HotSpot虛拟機, 并于2006年底開源, 主要使用C++實作, JNI接口部分用C實作.

HotSpot是比較新的JVM, 用來替代JIT (Just in Time, 即時編譯), 可以大大提高Java的運作性能 —— 通過下述方法提高性能:

Java起初是将源代碼編譯class位元組碼在虛拟機上執行, 速度較慢;

HotSpot将常用的部分代碼編譯為本地(native)代碼, 顯著提高性能.

HotSpot JVM參數分為标準參數(standard options)、非标準參數(non-standard options) 以及非穩定參數, 可參考: 關于JVM的垃圾回收(GC) 這可能是你想了解的 中

4.1 參數名稱的說明

.

關于HotSpot VM以及Java語言的動态編譯 你可能想知道這些

HotSpot包括一個解釋器和兩個編譯器(client和server, 實際運作中選擇其一即可, 大多選擇server), 解釋與編譯混合執行模式, 預設啟動解釋執行.

server

模式下應用程式啟動較慢, 占用記憶體多, 但執行效率高, 其适用于伺服器端需要長期執行的應用;

client

模式下應用程式啟動較快, 占用記憶體小, 但執行效率較低, 預設情況下不進行動态編譯, 适用于桌面應用程式.

(1) 檢視 JVM 的啟動模式:

# 使用解釋與編譯混合的模式
java -version
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)
# mixed mode 解釋與編譯混合的模式, 是預設使用的模式. 
           
# 使用純解釋模式
java -Xint -version
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
# interpreted mode 純解釋模式, 即禁用JIT編譯. 
           
# 使用純編譯模式
java -Xcomp -version
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, compiled mode)
# compiled mode 純編譯模式, 如果方法無法編譯, 則回退到解釋模式執行無法編譯的方法. 
           

Java源代碼被編譯器編譯成class位元組碼檔案, 位元組碼在運作時可以被動态編譯(JIT)成本地代碼, 前提是解釋與編譯混合執行模式且虛拟機不是剛啟動.

解釋器用來解釋class位元組碼檔案, Java是解釋型語言(差別于編譯型語言).

計算機不能直接了解執行進階語言, 隻能直接執行機器語言, 是以必須将進階語言翻譯成機器語言再執行.

翻譯的方式有兩種 —— 編譯和解釋, 兩者隻是翻譯的時間不同:

① 解釋型語言: 不需要提前翻譯 —— 例如Java語言, 在運作時才翻譯, 再由專門的解釋器解釋執行 —— 每執行一次就要翻譯一次, 效率較低.

優點: 可移植性好, 隻要有解釋環境, 就可以在不同的作業系統上運作. 比如在解釋執行時可以動态改變變量的類型、修改程式以及在程式中插入良好的調試診斷等資訊, 将解釋器移植到不同的系統上,則程式不用改動就可以在移植了解釋器的系統上運作。

缺點: 運作需要解釋環境, 運作速度較慢, 占用的資源更多 —— 因為不僅要為使用者程式配置設定空間, 解釋器本身也要占用一定的系統資源. 其封裝了底層代碼, 程式嚴重依賴平台, 不能同C++那樣直接操作底層.

代表: 一些網頁腳本、伺服器腳本等對速度要求不高, 卻對不同系統平台間的相容性有要求的程式通常使用解釋性語言, 如Java、JavaScript、Perl、Python、Ruby、MATLAB等.

② 編譯型語言: 編寫的程式在運作前, 需要通過編譯器将代碼編譯成機器語言(二進制檔案), 然後直接由相應的作業系統執行.

編譯和執行是分開的, 但不能跨平台. 例如 C++ 編譯成的 exe 檔案, 運作時不需再次編譯, 直接使用編譯的結果即可 —— 效率較高.

因為不同的作業系統識别的二進制檔案是不同的, 是以編譯型語言的程式在移植後, 需要重新編譯(如Windows下的C程式編譯成exe檔案, Linux下要編譯成erp檔案).

優點: 運作速度快, 代碼效率高, 同等條件下對系統要求較低.

缺點: 代碼需要經過編譯才能運作, 可移植性差 —— 隻能在相容的作業系統上運作.

代表: 像開發作業系統、大型應用程式、資料庫系統等時都使用編譯型語言, 如C、C++、Pascal等.

動态編譯 (compile during run-time), 英文稱 Dynamic compilation, Just In Time (即時編譯) 也有此意.

HotSpot VM對位元組碼的編譯不是在程式運作前, 而是在程式運作過程中編譯的.

HotSpot VM中有一個螢幕 (Profile Monitor), 用來監視程式的運作狀況.

Java位元組碼 (class檔案) 是以解釋的方式被加載到虛拟機中 (預設啟動時就解釋執行), 程式運作過程中, 使用頻率高、對程式的性能影響重要的代碼, 稱之為熱點 (hotspot), HotSpot VM會把這些熱點動态地編譯成機器碼 (native code), 同時對機器碼進行優化, 進而提高運作效率. 對使用頻率較低的代碼, HotSpot VM就不會編譯.

比如指令的重排序, 使用

volatile

關鍵字可以禁止重排序等類似的操作都是在這個編譯階段進行的.

① 不編譯: 位元組碼加載到虛拟機中時的狀态, 也就是虛拟機執行時再編譯;

② 編譯: 把位元組碼編譯成本地代碼, 虛拟機執行時已經編譯好了, 無需再次編譯;

③ 編譯并優化: 不但把位元組碼編譯成本地代碼, 而且還進行了優化.

具體如何處理, 都是由螢幕 (Profile Monitor) 決定的.

為什麼不采取将位元組碼直接變異成本地代碼, 然後再裝載到虛拟機中?

① 動态編譯器在許多方面比靜态編譯器優越 —— 靜态編譯器通常很難預知程式運作過程中最需要優化的代碼.

② 函數調用是很浪費系統時間的, 因為有許多進出棧操作. 是以有一種優化辦法, 就是把原來的函數調用通過編譯, 改為非函數調用 —— 将函數代碼直接嵌到調用的地方, 變為順序執行.

③ 面向對象的語言支援多态, 靜态編譯無法确定程式調用的到底是超類的哪些實作子類的方法, 因為多态是在程式運作中才能具體确定的.

OpenJDK和Sun/OracleJDK 差別 與聯系

【Language】解釋性語言和編譯型語言的差別和不同

作者: 馬瘦風

出處: 部落格園 馬瘦風的部落格

您的支援是對部落客的極大鼓勵, 感謝您的閱讀.

本文版權歸部落客所有, 歡迎轉載, 但請保留此段聲明, 并在文章頁面明顯位置給出原文連結, 否則部落客保留追究相關人員法律責任的權利.