首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

深入剖析 OpenJDK HotSpot VM 即時編譯(JIT)與分層編譯機制

     編輯:Java 綜合教學

深入剖析 OpenJDK HotSpot VM 即時編譯(JIT)與分層編譯機制

OpenJDK HotSpot JVM 由執行引擎(垃圾回收器、即時編譯器)和運行時(類加載、字節碼驗證、解釋器)組成。本文聚焦 JIT 編譯器,特別是 JDK 8 默認的分層編譯架構及其優化技術。

核心亮點

  • 應用程序可選擇適當的 JIT 編譯器實現接近機器代碼性能
  • 分層編譯由 5 個層次組成,兼顧啟動速度與峰值性能
  • 提供豐富 JVM 診斷開關(-XX:+PrintCompilation 等)
  • 內聯、向量化、逃逸分析等優化進一步提升性能

執行引擎與編譯器架構

HotSpot 包含兩類編譯器:

  • C1 (Client Compiler):啟動快,優化程度較低,適合客戶端應用
  • C2 (Server Compiler):編譯閾值高(默認 10000),針對熱點方法生成高度優化代碼

JDK 8 默認啟用 分層編譯,結合 C1 和 C2 優勢。可通過 -XX:-TieredCompilation 禁用,退回純 C2 模式。

JVM 架構圖 執行引擎組件

分層編譯的五個層次

層次名稱特點
0解釋執行收集性能分析數據,識別熱點方法
1簡單 C1 編譯無性能分析信息,快速編譯
2受限 C1 編譯少量方法編譯,收集調用次數、循環分支信息
3完整 C1 編譯所有 C1 編譯方法及完整性能分析信息
4C2 編譯服務端編譯器,最高優化級別

分層編譯通過低層次快速編譯改善啟動性能,高層次利用收集的性能分析信息生成高度優化代碼。

代碼緩存與閾值調優

  • 編譯後代碼存儲在 代碼緩存,大小固定。分層編譯默認 240MB,非分層 48MB。
  • 緩存滿時 JVM 停止編譯,建議通過 -XX:ReservedCodeCacheSize 增大。
  • 各層獨立閾值可調(如 -XX:Tier3MinInvocationThreshold),第三層最低調用閾值 100,遠低於非分層 C1 的 1500,導致編譯更頻繁。

編譯診斷:-XX:+PrintCompilation

輸出格式:timestamp compilation-id flags tiered-level class::method @osr_bci code-size [deoptimization]

567 693 % ! 3 org.h2.command.dml.Insert::insertRows @ 76 (513 bytes)
656 797 n 0 java.lang.Object::clone (native)
779 835 s 4 java.lang.StringBuffer::append (13 bytes)
  • %:OSR (On-Stack Replacement) 方法
  • !:有異常處理器
  • s:同步方法
  • n:原生方法
  • 層次 3/4 表示分層編譯階段

動態去優化

類加載導致優化假設失效時,JVM 執行去優化:方法從高層退回低層或標記為 "not entrant"/"zombie" 待回收。PrintCompilation 會輸出 made not entrant、made zombie 等標記。

關鍵優化技術

內聯

將調用替換為方法體,消除調用開銷。-XX:+PrintInlining 可查看決策:

@ 80 java.io.BufferedInputStream::getBufIfOpen (21 bytes) inline (hot)
@ 91 java.lang.System::arraycopy (0 bytes) (intrinsic)
@ 76 java.util.zip.Inflater::setInput (74 bytes) too big

受方法大小、調用熱度限制。intrinsic 表示內部函數(手工優化的特殊方法,如 System.arraycopy)。

向量化

利用 SIMD 指令並行處理數據。HotSpot 提供兩級支持:

  • 內部循環樁優化(類似內部函數)
  • 基於 MIT SLP 論文的超級字自動向量化,優化固定展開的數組操作
a[j] = b + c * z[i]  // 展開後可自動向量化

逃逸分析

判斷對象是否逃逸出方法/線程。未逃逸對象可:

  • 標量替換:字段存入寄存器,消除堆分配
  • 鎖消除:移除同步鎖
  • 優化比較:使用高效指令

其他優化

  • 循環展開:減少迭代開銷,助力向量化
  • 公共子表達式消除、死代碼消除等經典編譯優化

總結

HotSpot 分層編譯通過多層次協作,在啟動速度與峰值性能間取得平衡。理解編譯層次、代碼緩存、診斷開關及核心優化(內聯、向量化、逃逸分析),有助於深度調優 JVM 性能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved