JVM即時編譯(JIT)

JVM基礎回顧

Java 作為一門高級程序語言,由于它自身的語言特性,它并非直接在硬件上運行,而是通過編譯器(前端編譯器)將 Java 程序轉換成該虛擬機所能識別的指令序列,也就是字節碼,然后運行在虛擬機之上的;JVM的存在主要

  • 提供了可移植性,一旦 Java 代碼被編譯為 Java 字節碼,便可以在不同平臺上的 Java 虛擬機實現上運行,選擇在虛擬機上實現就可以避免在硬件上實現的高成本
  • 提供了一個代碼托管的環境,代替我們處理部分冗長而且容易出錯的事務,例如內存管理。以及在這個運行時的環境里可以加入垃圾回收,類型檢查,安全權限等功能,使開發人員免于書寫無關業務邏輯的代碼,提升開發效率

那么我們知道從硬件視角來看,Java 字節碼無法直接執行。因此,Java 虛擬機需要將字節碼翻譯成機器碼。這里也是java與一些靜態編譯語言的不同。

在 HotSpot 里面,上述翻譯過程有兩種形式:第一種是解釋執行,即逐條將字節碼翻譯成機器碼并執行;第二種是即時編譯(Just-In-Time compilation,JIT),即將一個方法中包含的所有字節碼編譯成機器碼后再執行。

前者的優勢在于啟動速度快,無需等待編譯,無額外內存占用;而后者的優勢在于實際運行速度更快,程序啟動后,編譯器逐漸發揮作用,把越來越多的熱點代碼優化編譯保存成成本地代碼,可以減少解釋器的中間消耗,提高執行效率。

HotSpot 默認采用混合模式,綜合了解釋執行和即時編譯兩者的優點。它會先解釋執行字節碼,而后將其中反復執行的熱點代碼,以方法為單位進行即時編譯。

Hot Spot即時編譯器

為了滿足不同用戶場景的需要,HotSpot 內置了多個即時編譯器:C1、C2 和 Graal(Java 10 引入的實驗性即時編譯器)。

C1 又叫做 Client 編譯器,面向的是對啟動性能有要求的客戶端程序,采用的優化手段相對簡單,因此編譯時間較短。

C2 又叫做 Server 編譯器,面向的是對峰值性能有要求的服務器端程序,采用的優化手段相對復雜,因此編譯時間較長,但同時生成代碼的執行效率較高。

在 Java 7 以前,我們需要根據程序的特性選擇對應的即時編譯器。啟動性能有要求的程序,我們采用編譯效率較快的 C1。對于執行時間較長的,或者對峰值性能有要求的程序,我們采用生成代碼執行效率較快的 C2。

Java 8 默認使用分層編譯,可以動態的選擇使用C1和C2編譯器。方法代碼會先被解釋器解釋執行,然后熱點方法首先會被 C1 編譯,而后熱點方法中的熱點會進一步被 C2 編譯。

分層編譯的引入在于讓即時編譯更具備靈性,針對不同代碼的實際情況選取最佳的編譯路徑,也是在程序啟動速度、編譯時間與運行效率之間達到最佳平衡。

那么具體分層編譯的運行機制是什么呢?(http://cr.openjdk.java.net/~iveresov/tiered/Tiered.pdf)

  1. 解釋執行;(帶 profiling , profiling 是指在程序執行過程中,收集能夠反映程序執行狀態的數據)
  2. 執行不帶 profiling 的 C1 代碼;
  3. 執行僅帶方法調用次數以及循環回邊執行次數 profiling 的 C1 代碼;
  4. 執行帶所有 profiling 的 C1 代碼;
  5. 執行 C2 代碼。

通常情況下,C2 代碼的執行效率要比 C1 代碼的高出 30% 以上。

對于 C1 代碼的三種狀態,按執行效率從高至低則是 1 層 > 2 層 > 3 層

即時編譯的觸發

Java 虛擬機是根據方法的調用次數以及循環回邊的執行次數來觸發即時編譯的。上邊提到,Java 虛擬機在分層編譯 0 層、2 層和 3 層執行狀態時進行 profiling,其中就包含方法的調用次數和循環回邊的執行次數。

循環回邊:字節碼中可以簡單理解為往回跳轉的指令;

具體來說,在不啟用分層編譯的情況下,當方法的調用次數和循環回邊的次數的和,超過由參數 -XX:CompileThreshold 指定的閾值時(使用 C1 時,該值為 1500;使用 C2 時,該值為 10000),便會觸發即時編譯。當啟用分層編譯時,Java 虛擬機將不再采用由參數 -XX:CompileThreshold 指定的閾值(該參數失效),而是使用另一套閾值系統。在這套系統中,閾值的大小是動態調整的。所謂的動態調整其實并不復雜:在比較閾值時,Java 虛擬機會將閾值與某個系數 s 相乘。該系數與當前待編譯的方法數目成正相關,與編譯線程的數目成負相關。

系數的計算方法為:

s = queue_size_X / (TierXLoadFeedback * compiler_count_X) +?1

其中X是執行層次,可取3或者4

queue_size_X是執行層次為X的待編譯方法的數目;

TierXLoadFeedback是預設好的參數,控制34層,其中Tier3LoadFeedback為5,Tier4LoadFeedback為3

compiler_count_X是層次X的編譯線程數目。

通常情況下,方法會首先被解釋執行,然后被 3 層的 C1 編譯,最后被 4 層的 C2 編譯。

http://cr.openjdk.java.net/~iveresov/tiered/Tiered.pdf

即時編譯的優化

基于分支的優化

假設應用程序調用該方法時,所傳入的 boolean 值皆為 true。那么針對兩次判斷,false跳轉的次數都為 0。C2 可以根據這兩個分支 profile 作出假設,在接下來的執行過程中,這兩個條件跳轉指令仍舊不會發生跳轉。基于這個假設,C2 便不再編譯這兩個條件跳轉語句所對應的 false 分支了。

那么優化后的C代碼將直接返回0

;

根據條件跳轉指令的分支 profile,即時編譯器可以將從未執行過的分支剪掉,以避免編譯這些很有可能不會用到的代碼,從而節省編譯時間以及部署代碼所要消耗的內存空間。分支 profile 出現僅跳轉或者僅不跳轉的情況并不多見。即時編譯器對分支 profile 的利用也不僅限于“剪枝”。它還會根據分支 profile,計算每一條程序執行路徑的概率,以便某些編譯器優化優先處理概率較高的路徑。當假設失敗的情況下,Java 虛擬機給出的解決方案便是去優化,即從執行即時編譯生成的機器碼切換回解釋執行

基于類型的優化

方法內聯

公共子表達式消除

數組邊界檢查消除

逃逸分析

總結:

1.即時編譯-將Java字節碼編譯成可優化可復用的機器碼,運行在底層硬件之上,這么做是為了提高代碼的執行效率,提高性能峰值,其觸發點是熱點代碼,熱點代碼是通過方法的調用次數或者回邊循環的次數來篩選的

2.分層編譯的引入是為了讓即時編譯更具備靈性,使得虛擬機可以根據實際運行情況以及相應的算法動態選擇執行代碼的編譯路徑,通常情況下,熱點方法會先被解釋執行,然后被C1編譯,再被C2編譯

? ?分層編譯是一種折衷的方式,既能夠滿足部分不熱的代碼能夠在短時間內執行完成,也能滿足很熱的代碼能夠擁有最好的優化、執行效率.

資料來源:

1.《深入拆解虛擬機》 鄭雨迪

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/75054.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/75054.shtml
英文地址,請注明出處:http://en.pswp.cn/web/75054.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

剛體碰撞檢測與響應(C++實現)

本文實現一個經典的物理算法:剛體碰撞檢測與響應。這個算法用于檢測兩個剛體(如矩形或圓形)是否發生碰撞,并在碰撞時更新它們的速度和位置。我們將使用C來實現這個算法,并結合**邊界框(Bounding Box&#x…

常用的國內鏡像源

常見的 pip 鏡像源 阿里云鏡像:https://mirrors.aliyun.com/pypi/simple/ 清華大學鏡像:https://pypi.tuna.tsinghua.edu.cn/simple 中國科學技術大學鏡像:https://pypi.mirrors.ustc.edu.cn/simple/ 豆瓣鏡像:https://pypi.doub…

鴻蒙小案例-京東登錄

效果 代碼實現 Entry Component struct Index {build() {Column() {Row() {Image($r(app.media.jd_cancel)).width(20)Text(幫助).fontSize(16).fontColor(#666)}.width(100%).justifyContent(FlexAlign.SpaceBetween)Image($r(app.media.jd_logo)).height(250).width(250)// …

《 Scikit-learn與MySQL的深度協同:構建智能數據生態系統的架構哲學》

在機器學習工程實踐中,數據存儲與模型訓練的割裂始終是制約算法效能的關鍵瓶頸。Scikit-learn作為經典機器學習庫,其與MySQL的深度協同并非簡單的數據管道連接,而是構建了一個具備自組織能力的智能數據生態系統。這種集成突破了傳統ETL流程的…

華為AI-agent新作:使用自然語言生成工作流

論文標題 WorkTeam: Constructing Workflows from Natural Language with Multi-Agents 論文地址 https://arxiv.org/pdf/2503.22473 作者背景 華為,北京大學 動機 當下AI-agent產品百花齊放,盡管有ReAct、MCP等框架幫助大模型調用工具&#xff0…

關于軟件bug描述

軟件缺陷(Defect),常常又被叫做Bug。 所謂軟件缺陷,即為計算機軟件或程序中存在的某種破壞正常運行能力的問題、錯誤,或者隱藏的功能缺陷。缺陷的存在會導致軟件產品在某種程度上不能滿足用戶的需要。IEEE729-1983對缺…

【元表 vs 元方法】

元表 vs 元方法 —— 就像“魔法書”和“咒語”的關系 1. 元表(Metatable):魔法書 是什么? 元表是一本**“規則說明書”**,它本身是一個普通的 Lua 表,但可以綁定到其他表上,用來定義這個表應該…

Spring Boot 通過全局配置去除字符串類型參數的前后空格

1、問題 避免前端輸入的字符串參數兩端包含空格,通過統一處理的方式,trim掉空格 2、實現方式 /*** 去除字符串類型參數的前后空格* author yanlei* since 2022-06-14*/ Configuration AutoConfigureAfter(WebMvcAutoConfiguration.class) public clas…

C語言核心知識點整理:結構體對齊、預處理、文件操作與Makefile

目錄 結構體的字節對齊預處理指令詳解文件操作基礎Makefile自動化構建總結 1. 結構體的字節對齊 字節對齊原理 內存對齊:CPU訪問內存時,對齊的地址能提高效率。操作系統要求變量按類型大小對齊。對齊規則: 每個成員的起始地址必須是min(成…

VBA+BOS單據+插件,解決計劃任務跟蹤的問題之二:導入ERP

第二步,就是要將拆分好的任務導入ERP了 1、將建一個BOS單據叫“任務池”,大概是這樣的 然后在拆分工具中進行導數據,點擊“數據導出準備”,跳轉到“導入ERP”界面,然后點“獲取數據”,將拆分好的數據轉過來…

使用uglifyjs對靜態引入的js文件進行壓縮

前言 因為有時候js文件沒有npm包,或者需要修改,只能引入靜態的js,那么這個時候就可以對js進行壓縮了。我其實想通過vite、webpack等插件進行壓縮的,可是他都不能定位到public目錄下面的文件,所以我只能自己壓縮了。編…

藍橋杯 web 水果拼盤 (css3)

做題步驟: 看結構:html 、css 、f12 分析: f12 查看元素,你會發現水果的高度剛好和拼盤的高度一樣,每一種水果的盤子剛好把頁面填滿了,所以咱們就只要讓元素豎著排列,加上是豎著,排不下的換行…

差分音頻轉單端音頻單電源方案

TI LMV321介紹 TI的LMV321是單通道的低壓軌到軌輸出運算放大器,適用于需要低工作壓、節省空間和低成本的應用。 其中,芯片設計中的軌到軌輸出(Rail-to-Rail Output) 是指通過特定的電路設計,使芯片(如運算…

Pandas 庫

Pandas 是一個開源的數據分析和數據處理庫,它是基于 Python 編程語言的。 Pandas 提供了易于使用的數據結構和數據分析工具,特別適用于處理結構化數據,如表格型數據 Pandas 是數據科學和分析領域中常用的工具之一,它使得用戶能夠…

Vue 3 的<Teleport>功能與用法

Vue 3 的 <Teleport> 功能與用法 1. 基本用法 <Teleport> 是 Vue 3 的一個內置組件&#xff0c;允許將組件的內容渲染到 DOM 中的任意位置&#xff0c;而不改變其邏輯結構。以下是基本用法&#xff1a; 定義目標 DOM 元素&#xff1a;<div id"teleport-…

MySQL隨機獲取記錄之方法(The Method of Randomly Obtaining Records in MySQL)

MySQL中如何隨機獲取一條記錄 隨機獲取一條記錄是在數據庫查詢中常見的需求&#xff0c;特別在需要展示隨機內容或者隨機推薦的場景下。在 MySQL 中&#xff0c;有多種方法可以實現隨機獲取一條記錄&#xff0c;每種方法都有其適用的情況和性能特點。在本文中&#xff0c;我們將…

synchronized鎖升級詳解

synchronized鎖升級詳解 synchronized是Java中實現線程同步的關鍵字&#xff0c;它在JVM內部實現了鎖的升級機制&#xff0c;從偏向鎖到輕量級鎖再到重量級鎖&#xff0c;這種優化是為了減少鎖操作帶來的性能開銷。 1. 鎖的四種狀態 Java對象頭中的Mark Word會記錄鎖的狀態&…

C++函數如何返回多個參數

在編程中&#xff0c;我們經常會遇到需要函數返回多個值的場景。雖然 C 函數不能直接返回多個參數&#xff0c;但通過一些間接的方法&#xff0c;我們可以輕松實現這一需求。本文將詳細介紹幾種常見的實現方式&#xff0c;并分析它們的優缺點和適用場景。 1. 引言 在 C 中&…

最新版PhpStorm超詳細圖文安裝教程,帶補丁包(2025最新版保姆級教程)

目錄 前言 一、PhpStorm最新版下載 二、PhpStorm安裝 三、PhpStorm補丁 四、運行PhpStorm 前言 PhpStorm 是 JetBrains 公司推出的 專業 PHP 集成開發環境&#xff08;IDE&#xff09;&#xff0c;專為提升 PHP 開發效率設計。其核心功能包括智能代碼補全、實時語法錯誤檢…

【雜談】Godot4.4導出到Android平臺(正式導出)

學博而后可約&#xff0c;事歷而后知要。 目錄 一、準備二、Gradle構建三、配置Java SDK四、配置Android SDK五、配置密鑰 一、準備 本文在前文【雜談】Godot4.4導出到安卓平臺&#xff08;調試導出&#xff09;的基礎上&#xff0c;進行正式導出。調試導出并不是真正的編譯導…