1. 程式人生 > >你應該知道的關於HotSpot VM的內容

你應該知道的關於HotSpot VM的內容

文章目錄
1 HotSpot VM的歷史
2 HotSpot VM 概述
2.1 編譯器
2.2 直譯器
2.3 解釋型語言 VS 編譯型語言
3 動態編譯
3.1 概述
3.2 HotSpot VM 對位元組碼的處理有三種
3.3 為什麼不靜態編譯
版權宣告
1 HotSpot VM的歷史
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) 以及非穩定引數, 可參考: GC學習入門 看這一篇就夠了(基於Oracle JDK 8)

2 HotSpot VM 概述

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

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

client 模式下應用程式啟動較快, 佔用記憶體小, 但執行效率較低, 預設情況下不進行動態編譯, 適用於桌面應用程式.

檢視 JVM 的啟動模式:

使用解釋與編譯混合的模式

java -version
java version “1.8.0_162”
Java™ SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot™ 64-Bit Server VM (build 25.162-b12, mixed mode)

mixed mode 解釋與編譯混合的模式, 是預設使用的模式.

1
2
3
4
5
6

使用純解釋模式

java -Xint -version
java version “1.8.0_162”
Java™ SE Runtime Environment (build 1.8.0_162-b12)

interpreted mode 純解釋模式, 即禁用JIT編譯.

1
2
3
4
5

使用純編譯模式

java -Xcomp -version
java version “1.8.0_162”
Java™ SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot™ 64-Bit Server VM (build 25.162-b12, compiled mode)

compiled mode 純編譯模式, 如果方法無法編譯, 則回退到解釋模式執行無法編譯的方法.

1
2
3
4
5
6
2.1 編譯器
Java 原始碼被編譯器編譯成 class 位元組碼檔案, 位元組碼在執行時可以被動態編譯(JIT)成原生代碼, 前提是解釋與編譯混合執行模式且虛擬機器不是剛啟動.

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

2.3 解釋型語言 VS 編譯型語言
計算機不能直接理解執行高階語言, 只能直接執行機器語言, 所以必須將高階語言翻譯成機器語言再執行.

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

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

優點: 可移植性好, 只要有解釋環境, 就可以在不同的作業系統上執行. 比如在解釋執行時可以動態改變變數的型別、修改程式以及在程式中插入良好的除錯診斷等資訊, 將直譯器移植到不同的系統上,則程式不用改動就可以在移植瞭解釋器的系統上執行。

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

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

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

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

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

優點: 執行速度快, 程式碼效率高, 同等條件下對系統要求較低.

缺點: 程式碼需要經過編譯才能執行, 可移植性差 —— 只能在相容的作業系統上執行.

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

3 動態編譯
3.1 概述
動態編譯 (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 關鍵字可以禁止重排序等都是在這個編譯階段進行的.

3.2 HotSpot VM 對位元組碼的處理有三種
① 不編譯: 位元組碼載入到虛擬機器中時的狀態, 也就是虛擬機器執行時再編譯;

② 編譯: 把位元組碼編譯成原生代碼, 虛擬機器執行時已經編譯好了, 無需再次編譯;

③ 編譯並優化: 不但把位元組碼編譯成原生代碼, 而且還進行了優化.

具體如何處理, 都是由監視器 (Profile Monitor) 決定的.

3.3 為什麼不靜態編譯
為什麼不採取將位元組碼直接變異成原生代碼, 然後再裝載到虛擬機器中?

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

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

③ 面向物件的語言支援多型, 靜態編譯無法確定程式呼叫的到底是超類的哪些實現子類的方法, 因為多型是在程式執行中才能具體確定的.

參考:

http://www.cnblogs.com/zengkefu/p/5633342.html

https://blog.csdn.net/u014647208/article/details/78329187