Java 編譯器


Javac編譯器

Javac 編譯過程大致可以分為1個准備過程和3個處理過程:

  1. 准備過程:初始化插入式注解處理器。
  2. 解析與填充符號表過程,包括:
    1. 詞法、語法分析,將源代碼的字符流轉變為標記集合,構造出抽象語法樹。
    2. 填充符號表,產生符號地址和符號信息。
  3. 插入式注解處理器的注解處理過程。可以把插入式注解處理器看作是一組編譯器的插件,當這些插件工作時,允許讀取、修改、添加抽象語法樹中的任意元素,如Lombok注解。
  4. 分析與字節碼生成過程,包括:
    1. 標注檢查。對語法的靜態信息進行檢查。
    2. 數據流及控制流分析。對程序動態運行過程進行檢查。
    3. 解語法糖。將簡化代碼編寫的語法糖還原為原有的形式。
    4. 字節碼生成。將前面各個步驟所生成的信息轉化成字節碼。

上述3個處理過程里,執行插入式注解時又可能會產生新的符號,如果有新的符號產生,就必須轉回到之前的解析、填充符號表的過程中重新處理這些新符號。javac編譯過程如下:

圖1-1 Javac 編譯過程

注解處理器

在JDK 6中提出並通過了JSR-269提案,該提案設計了一組被稱為“插入式注解處理器”的標准API,可以提前至編譯期對代碼中的特定注解進行處理,從而影響到前端編譯器的工作過程。可以把插入式注解處理器看作是一組編譯器的插件,當這些插件工作時,允許讀取、修改、添加抽象語法樹中的任意元素
如果這些插件在處理注解期間對語法樹進行過修改,編譯器將回到解析及填充符號表的過程重新處理,直到所有插入式注解處理器都沒有再對語法樹進行修改為止。典型示例為Lombok,它可以通過注解來實現自動產生getter/setter方法、進行空置檢查、生成受查異常表、產生equals()和hashCode()方法等等。
要通過注解處理器API實現一個編譯器插件,實現注解處理器的代碼需要繼承抽象類javax.annotation.processing.AbstractProcessor並重寫其抽象方法。

即時編譯器

目前主流的兩款商用Java虛擬機(HotSpot、OpenJ9)里,Java程序最初都是通過解釋器(Interpreter)進行解釋執行的,當虛擬機發現某個方法或代碼塊的運行特別頻繁,就會把這些代碼認定為熱點代碼(Hot Spot Code),為了提高熱點代碼的執行效率,在運行時,虛擬機將會把這些代碼編譯成本地機器碼,並以各種手段盡可能地進行代碼優化,運行時完成這個任務的**后端編譯器被稱為即時編譯器。

解釋器與編譯器

HotSpot 虛擬機內部同時包含解釋器與編譯器,兩者相輔相成地配合完成工作。解釋器與編譯器兩者各有優勢:當程序需要迅速啟動和執行的時候,解釋器可以首先發揮作用,省去編譯的時間,立即運行。當程序啟動后,隨着時間的推移,編譯器逐漸發揮作用,把越來越多的代碼編譯成本地代碼,這樣可以減少解釋器的中間損耗,獲得更高的執行效率。當程序運行環境中內存資源限制較大,可以使用解釋執行節約內存(如部分嵌入式系統中和大部分的JavaCard應用中就只有解釋器的存在),反之可以使用編譯執行來提升效率。

圖1-2 解釋器與編譯器的交互

HotSpot虛擬機中內置了兩個即時編譯器,分別被稱為“客戶端編譯器”(Client Compiler)和“服務端編譯器”(Server Compiler),或者簡稱為C1編譯器和C2編譯器。C1擁有更快地編譯速度,而C2擁有更好地編譯質量。用戶也可以使用“-client”或“-server”參數去強制指定虛擬機運行在客戶端模式還是服務端模式。

無論采用的編譯器是客戶端編譯器還是服務端編譯器,解釋器與編譯器搭配使用的方式在虛擬機中被稱為“混合模式”(Mixed Mode),也可以使用參數“-Xint”強制虛擬機運行於“解釋模式”(Interpreted Mode),這時候編譯器完全不介入工作,全部代碼都使用解釋方式執行。另外,也可以使用參數“-Xcomp”強制虛擬機運行於“編譯模式”(Compiled Mode),這時候將優先采用編譯方式執行程序,但解釋器仍要在編譯無法進行的情況下介入執行過程。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM