參數設置
hotspot jvm 內置了兩個jit編譯器,分別是client compiler(C1編譯器)和server compiler(C2編譯器),可通過下列指令顯式指定使用哪種即時編譯器
-client 指定java虛擬機運行在client模式下,並使用C1編譯器;
特點:C1編譯器會堆字節碼進行簡單和可靠的優化,耗時短。以達到更快的編譯速度。
-server 指定java虛擬機運行在server模式下,並使用C2編譯器。
特點:C2進行較長時間的優化,以及激進優化。但優化的代碼執行效率更高。
C1和C2編譯器的優化策略不同
C1主要有方法內聯,去虛擬化冗余消除
方法內聯:將引用函數代碼編譯到引用點處,這樣可以減少棧幀的生成,減少參數傳遞以及跳轉過程
去虛擬化:對唯一的實現類進行內聯
冗余消除:在運行期間,把一些不會運行的代碼折疊掉
C2的優化主要是在全局層面,逃逸分析是優化的基礎,基於逃逸分析在C2上有如下幾種優化
標量替換:用標量值替換聚合對象的屬性值
棧上分配:對於未逃逸的對象分配對象在棧而不是堆
同步消除:清除同步操作,通常指synchronized
分層編譯策略:
程序解釋執行(不開啟性能監控)可以觸發C1編譯,將字節碼編譯成機器碼,可以進行簡單優化,也可以加上性能監控,C2編譯會根據性能監控信息進行激進優化。
當顯式指定了-server 時,默認開啟分層編譯策略,由C1編譯器和C2編譯器相互協作共同來執行編譯任務。
此外:
在JDK10 之后Hotspot又加入了一個全新即時編譯器:Graal編譯器,目前處於實踐狀態
可以通過-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler 去激活,才可以使用
JDK9版本引入了AOT編譯器(Ahead of time compiler 靜態提前編譯器)
AOT編譯工具jaotc,它借助Graal編譯器,將所輸入的java類文件轉換成機器碼,並存放至生成動態共享庫之中
所謂的AOT編譯,是與即時編譯相對立的一個概念,即時編譯指的是在程序的運行過程中,將字節碼轉換為可在硬件上直接運行的機器碼,並部署至托管環境中的過程,而AOT編譯指的是,在程序運行前,,便將字節碼轉換為機器碼的過程;
好處:
java虛擬機加載已經與編譯成二進制庫,可以直接運行。不必等即時編譯器的預熱,減少java應用第一次運行慢的體驗
缺點:
破壞了java“一次編譯到處運行”,必須為每個不同硬件,os編譯對應的發行包
降低了java鏈接過程的動態性,加載的代碼在編譯器就全部已知;
還需要繼續優化中,最初只支持Linux X64 java base