Java三種編譯方式
Java程序代碼需要編譯後才能在虛擬機中運行,編譯涉及到非常多的知識層面:編譯原理、語言規範、虛擬機規範、本地機器碼優化等;了解編譯過程有利於了解整個Java運行機制,不僅可以使得我們編寫出更優秀的代碼,而且還可以使得在JVM調優時更得心應手。
下面我們先來看下Java體系中的三種編譯方式:前端編譯、即時編譯(JIT編譯)、靜態提前編譯(AOT編譯),先來了解它們各有什麽優點和缺點,再來看看主流的前端編譯+JIT編譯方式的運作過程。
1、前端編譯
把Java源碼文件(.java)編譯成Class文件(.class)的過程;
也即把滿足Java語言規範的程序轉化為滿足JVM規範所要求格式的功能;
優點:
這階段的優化是指程序編碼方面的;
許多Java語法新特性("語法糖":泛型、內部類等等),是靠前端編譯器實現的,而不是依賴虛擬機;
編譯成的Class文件可以直接給JVM解釋器解釋執行,省去編譯時間,加快啟動速度;
缺點:
對代碼運行效率幾乎沒有任何優化措施;
解釋執行效率較低,所以需要結合下面的JIT編譯;
前端編譯器:Oracle javac、Eclipse JDT中的增量式編譯器(ECJ)等;
2、後端編譯/即時(JIT)編譯
通過Java虛擬機(JVM)內置的即時編譯器(Just In Time Compiler,JIT編譯器);在運行時把Class文件字節碼編譯成本地機器碼的過程;
優點:
通過在運行時收集監控信息,把"熱點代碼"(Hot Spot Code)編譯成與本地平臺相關的機器碼,並進行各種層次的優化;
可以大大提高執行效率;
缺點:
收集監控信息影響程序運行;
編譯過程占用程序運行時間(如使得啟動速度變慢);
編譯機器碼占用內存;
JIT編譯器:HotSpot虛擬機的C1、C2編譯器等;
另外,JIT編譯速度及編譯結果的優劣,是衡量一個JVM性能的很重要指標;
所以對程序運行性能優化集中到這個階段;
也就是說可以對這個階段進行JVM調優;
3、靜態提前編譯(Ahead Of Time,AOT編譯)
程序運行前,直接把Java源碼文件(.java)編譯成本地機器碼的過程;
優點:
編譯不占用運行時間,可以做一些較耗時的優化,並可加快程序啟動;
把編譯的本地機器碼保存磁盤,不占用內存,並可多次使用;
缺點:
因為Java語言的動態性(如反射)帶來了額外的復雜性,影響了靜態編譯代碼的質量;
一般靜態編譯不如JIT編譯的質量,這種方式用得比較少;
靜態提前編譯器(AOT編譯器):JAOTC、GCJ、Excelsior JET、ART (Android Runtime)等;
Java三種編譯方式