日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java 虚拟机探索之路系列】:JIT编译器

發布時間:2024/4/17 java 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java 虚拟机探索之路系列】:JIT编译器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【Java 虛擬機探索之路系列】:JIT編譯器

作者:郭嘉
郵箱:allenwells@163.com
博客:http://blog.csdn.net/allenwells
github:https://github.com/AllenWell

為什么會Java虛擬機會同一時候存在解釋器和編譯器呢?

這是為了兼顧啟動效率和運行效率兩個方面。Java程序最初是通過解釋器進行解釋運行的,當虛擬機返現某個方法或代碼塊的運行特別頻繁時,就會把這段代碼標記為熱點代碼,為了提供熱點代碼的運行效率,在運行時,虛擬機就會把這些代碼編譯成與本地平臺相關的機器碼。并進行各種層次的優化。

當編譯器做的激進優化不成立,不如載入了新類后類型繼承結構出現變化。出現了罕見陷阱時能夠進行逆優化退回到解釋狀態繼續運行。

以上描寫敘述的兩種配合關系例如以下圖所看到的:

一 編譯模式

HotSpot JVM內置了兩個編譯器,各自是Client Complier和Server Complier,虛擬機默認是Client模式。我們也能夠通過

  • -client:強制虛擬機運行Client模式
  • -server:強制虛擬機運行Server模式

而不管是Client模式還是Server模式,虛擬機都會運行在解釋器和編譯器配合使用的混合模式下。能夠通過

  • -Xint:強制虛擬機運行于解釋模式
  • -Xcomp:強制虛擬機運行于編譯模式

以上描寫敘述的運行模式例如以下圖所看到的:

二 分層編譯

為什么會存在分層編譯?

這是由于編譯器編譯本機代碼須要占用程序運行時間,要編譯出優化程度更高的代碼鎖花費的時間可能更長,并且想要編譯出優化程度更高的代碼,解釋器可能還要替編譯器收集性能監控信息。這對解釋運行的速度也有影響。為了在程序啟動響應速度和運行效率之間尋找平衡點。因此採用分層編譯的策略。

分層策略例如以下所看到的:

  • 第0層:程序解釋運行。解釋器不開啟性能監控功能,可觸發第1層編譯。
  • 第1層:即C1編譯。將字節碼編譯為本地代碼。進行簡單和可靠的優化,如有必要將增加性能監控的邏輯。
  • 第2層:即C2編譯,將字節碼編譯為本地代碼,同一時候啟用一些編譯耗時較長的優化,甚至會依據性能監控信息進行一些不可靠的激進優化。

三 編譯對象

編譯對象即為會被編譯優化的熱點代碼。有下面兩類:

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

四 觸發條件

上面描寫敘述中使用多次這個概念,那么什么算多次呢?

這就牽扯到觸發條件這個概念,推斷一段代碼是否是熱點代碼。是否須要觸發即時編譯,這樣的行為成為熱點探測(Spot Dectection)。

熱點探測有兩種手段:

4.1 基于採樣的熱點探測(Sample Based Hot Spot Dectection)

虛擬機會周期性的檢查各個線程的棧頂,假設發現某些方法常常性的出如今棧頂,那么這種方法就是熱點方法。

4.2 基于計數器的熱點探測(Counter Based Hot Spot Dectection)

虛擬機會為每一個方法或代碼塊建立計數器,統計方法的運行次數。假設運行次數超過一定的閾值就覺得他是熱點方法。

HotSpot JVM使用另外一種方法基于計數器的熱點探測方法。它為每一個方法準備了兩類計數器:

4.2.1 方法調用計數器

這個閾值在Client模式下是1500次。在Server模式下是10000此,這個閾值能夠通過參數-XX:CompileThreadhold來人為設定。

假設不做不論什么設置。方法調用次數統計的并非方法被調用的絕對次數,而是相對的運行頻率,即一段時間內方法被調用的次數,當超過一定時間限度,假設方法的調用次數仍然不足以讓它提交給即時編譯器編譯,那這種方法的調用計數器會被降低一半,這個過程被稱為方法調用計數器的熱度衰減(Counter Decay)。而這段時間就稱為此方法統計的半衰周期(Counter Half Life Time)。相同也能夠使用參數-XX:-UseCounterDecay來關閉熱度衰減。

方法調用計數器觸發即時編譯的整個流程例如以下圖所看到的:

4.2.2 回邊計數器

什么是回邊?
在字節碼遇到控制流向后跳轉的指令稱為回邊(Back Edge)。

回邊計數器是用來統計一個方法中循環體代碼運行的次數,回邊計數器的閾值能夠通過參數-XX:OnStackReplacePercentage來調整。

  • 虛虛擬機運行在Client模式下,回邊計數器閡值計算公式為:
方法調用計數器閉值( CompileThreshold) xOSR比率(OnStackReplacePercentage) / 100

當中OnSlackReplacePercentage默認值為933,假設都取默認值.那Client模式虛擬機的回邊計數器的閡值為13995.

  • 虛擬機運行在Servo模式下,回邊計數器閡值的itm公式為:
方法調用計數器閡值(CompileThmshold) x (OSR比率(OnStackReplacePercentage) - 解釋器監控比率(InterpreterProffePercentage) / 100

當中OnStackReplacePementage默認值為140. InterpreterPmfilePercenmgc默認值為33.
假設都取默認值。BF Server模式虛擬機回邊計數器的闌值為10700。

回邊計數器觸發即時編譯的流程例如以下圖所看到的:

回邊計數器與方法調用計數器不同的是,回邊計數器沒有熱度衰減,因此這個計數器統計的就是循環運行的絕對次數。

五 編譯流程

在默認設置下,不管是方法調用產生的即時編譯請求,還是OSR編譯請求,虛擬機在代碼編譯器還未完畢之前,都仍然依照解釋方式繼續進行,而編譯動作則在后臺的編譯線程中繼續進行。也能夠使用-XX:-BackgroundCompilation來禁止后臺編譯,則此時一旦遇到JIT編譯,運行線程向虛擬機提交請求后會一直等待,直到編譯完畢后再開始運行編譯器輸出的本地代碼。

那么在后臺編譯過程中,編譯器做了什么事呢?

Server Compiler和Client Compiler的后臺編譯過程是不一樣的,我們來分別看一下。

5.1 Client Compiler編譯流程

  • 第一階段:一個平臺獨立的前端將字節碼構造成一種高級中間碼表示(High Level Infermediate Representaion),HIR使用靜態單分配的形式來表示代碼值,這能夠使得一些的構造過程之中和之后進行的優化動作更easy實現,在此之前編譯器會在字節碼上完畢一部分基礎優化,如方法內聯、常量傳播等。
  • 第二階段:一個平臺相關的后端從HIR中產生低級中間代碼表示(Low Level Intermediate Representation),而在此之前會在HIR上完畢還有一些優化。如空值檢查消除、范圍檢查消除等。以便讓HIR達到更高效的代碼表示形式。
  • 第三階段:在平臺相關的后端使用線性掃描算法(Linear Scan Register Allocation)在LIR上分配寄存器,并在LIR上做窺孔優化(Peephole)優化,然后產生機器碼。
  • 整個步驟例如以下圖所看到的:

    5.1 Server Compiler編譯流程

    Server Compiler是專門面向服務端的典型應用并為服務器的性能配置特別調整過的編譯器,它會運行全部經典的優化動作。例如以下所看到的:

    • 無用代碼消除
    • 循環展開
    • 循環表達式外提
    • 消除公共子表達式
    • 常量傳播
    • 基本塊重排序
    • 范圍檢查消除
    • 空值檢查消除
    • 守護內聯
    • 分支頻率預測
    posted on 2017-07-18 10:29 mthoutai 閱讀(...) 評論(...) 編輯 收藏

    轉載于:https://www.cnblogs.com/mthoutai/p/7199091.html

    總結

    以上是生活随笔為你收集整理的【Java 虚拟机探索之路系列】:JIT编译器的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。