Java JIT Just In Time 即時編譯

更多 Java 虛擬機(jī)方面的文章,請參見文集《Java 虛擬機(jī)》


前端編譯器 VS 后端編譯器

  • 前端編譯器:javac 編譯,在程序運(yùn)行前,將 源文件 轉(zhuǎn)化為 字節(jié)碼 即 .class 文件
    • Java 程序最初只能通過解釋器解釋執(zhí)行,即 JVM 對字節(jié)碼逐條解釋執(zhí)行,因此執(zhí)行速度比較慢。
    • 字節(jié)碼與平臺無關(guān)
  • 后端編譯器:JIT 編譯,在程序運(yùn)行期間,將 字節(jié)碼 轉(zhuǎn)化為 機(jī)器碼
    • 機(jī)器碼與平臺相關(guān)

JIT 即時編譯

當(dāng) JVM 發(fā)現(xiàn)某個方法或代碼塊執(zhí)行特別頻繁時,就將其認(rèn)定為 熱點(diǎn)代碼(Hot Spot Code)。在程序運(yùn)行期間,JVM 將這些熱點(diǎn)代碼編譯為與本地平臺相關(guān)的機(jī)器碼,并進(jìn)行各層次的優(yōu)化,從而提升熱點(diǎn)代碼的執(zhí)行效率。

基本流程如下:


JIT 即時編譯

如何檢測熱點(diǎn)代碼(Hot Spot Code):

  • 基于 采樣 的熱點(diǎn)檢測:檢查各個線程的棧頂。
  • 基于 計(jì)數(shù)器 的熱點(diǎn)檢測:HotSpot 虛擬機(jī)采用:
    • 方法計(jì)數(shù)器:統(tǒng)計(jì)每個方法調(diào)用的次數(shù)
    • 回邊計(jì)數(shù)器:統(tǒng)計(jì)每個方法中循環(huán)體代碼執(zhí)行的次數(shù)

即時編譯的設(shè)置及優(yōu)化

初級調(diào)優(yōu)

HotSpot 虛擬機(jī)內(nèi)置兩個 JIT 編譯器:

  • 客戶模式 Client Compiler,即 C1 編譯
    • 無采樣,立即 JIT 編譯,輕量優(yōu)化
    • JIT 編譯的類較多,可能導(dǎo)致代碼緩存不夠用
    • 速度較快,適用于短暫的應(yīng)用程序
  • 服務(wù)器模式 Server Compiler,即 C2 編譯
    • 采集 一萬次 調(diào)用樣本后深度編譯優(yōu)化
    • JIT 編譯的類較少
    • 啟動速度較慢,運(yùn)行起來后性能逐步提升
    • 每次 GC,計(jì)數(shù)器衰減一半
    • 可以設(shè)置 -XX:-UseCounterDelay 來禁止衰減

Java 8 支持多層編譯,即程序啟動時使用 C1 編譯,樣本足夠后使用 C2 編譯:

  • 禁止多層編譯:-XX:-TieredCompilation
  • 啟用多層編譯:-XX:+TieredCompilation

優(yōu)化代碼緩存

如果緩存過小,有些熱點(diǎn)代碼可能不會被 JIT 編譯。
C1 編譯的類較多,可能導(dǎo)致代碼緩存不夠用。
設(shè)置代碼緩存大小:-XX:ReservedCodeCacheSize = 32m

編譯閾值

即計(jì)數(shù)器的閾值,默認(rèn)為10000,即方法計(jì)數(shù)器和回邊計(jì)數(shù)器的總和達(dá)到了10000就觸發(fā) JIT 編譯。
設(shè)置編譯閾值:-XX:CompileThreshold = 10000

內(nèi)聯(lián) Inline

將方法的代碼復(fù)制到發(fā)起調(diào)用的方法里,以消除方法調(diào)用。
因?yàn)檎{(diào)用一個小方法可能比直接執(zhí)行該小方法對應(yīng)的代碼更耗時。

  • -XX:MaxInlineSize=35byte:能被內(nèi)聯(lián)的方法最大字節(jié)碼大小
  • -XX:FreqInlineSize=325byte:頻繁調(diào)用的方法能被內(nèi)聯(lián)的最大字節(jié)碼大小

如何讓方法更容易被內(nèi)聯(lián):拆分不常訪問的路徑。例如:

public void f() {
  if(most case) {
    ...
  }
  else {
    ... // 將不常訪問的路徑的代碼拆分到函數(shù) g() 中
    ... // 以降低整體代碼的大小,使得 most case 中的代碼可以被內(nèi)聯(lián)
  }
}

打印 JIT 編譯信息

java -XX:PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:PrintInline > a.out

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 《深入理解Java虛擬機(jī)》筆記_第一遍 先取看完這本書(JVM)后必須掌握的部分。 第一部分 走近 Java 從傳...
    xiaogmail閱讀 5,473評論 1 34
  • 這篇文章是我之前翻閱了不少的書籍以及從網(wǎng)絡(luò)上收集的一些資料的整理,因此不免有一些不準(zhǔn)確的地方,同時不同JDK版本的...
    高廣超閱讀 16,054評論 3 83
  • java編譯器,java解釋器 1.java程序是一種可跨平臺執(zhí)行的語言,之所以可以跨平臺,是因?yàn)閖vm的存在,J...
    rabbit_coding閱讀 7,124評論 2 17
  • 注:此文是我在讀完周志明老師的深入理解Java虛擬機(jī)之后總結(jié)的一篇文章,請閱讀此書獲取更加詳細(xì)的信息. 在這篇文章...
    AlstonWilliams閱讀 1,344評論 0 1
  • 對我來說基本上每次買衣服都是一場內(nèi)心的戰(zhàn)役,總是糾結(jié)買哪個,總是覺得沒有自己喜歡的。其實(shí)細(xì)細(xì)想來,不是...
    loverewards閱讀 251評論 0 0

友情鏈接更多精彩內(nèi)容