1. 程式人生 > >Java編譯期的前端過程

Java編譯期的前端過程

源代碼 將實例 調用父類 機器 tro 分享 jdk 即時編譯 開始

Java編譯期的概念

編譯期即將源代碼轉變成本地代碼的過程,對於Java來說,這個過程會更加的多樣。
Java編譯期因為采用的編譯器類型不同而導致概念也不同,Java編譯器可以分為以下三種類型:

  • 前端編譯器

    前端編譯器將java源代碼轉變成字節碼,常見的前端編譯器包括Javac編譯器、ECJ編譯器(Eclipse JDT)。

  • 即時(JIT,Just In Time)編譯器

    即時編譯器將字節碼轉變成本地機器碼,常見的即時編譯器包括HotSpot 虛擬機的C1、C2編譯器。

  • AOT(Ahead of Time)編譯器

    AOT編譯器直接將java源代碼變成本地機器碼,常見的AOT編譯器包括GCJ編譯器(GNU Compiler for the Java)

本文主要闡述Java前端編譯器的工作流程。

Javac 編譯器的編譯過程

Javac編譯器本身也是采用Java語言實現的一款前端編譯器,Javac編譯的流程如下圖所示:

技術分享圖片

  • 解析與填充符號表

    這個過程主要包含兩個部分:詞法語法分析和填充符號表
    詞法分析即將java源代碼轉換成token,語法分析再根據token構造出抽象語法樹(AST,Abstract Syntax Tree)。然後根據詞法語法分析之後的結果填充符號表。

  • 插入式註解處理

    JDK 1.6開始提供了一組插入式的註解處理器API,可以實現在編譯期間對註解進行處理,通過實現插入式註解處理器可以訪問和修改抽象語法樹中的任意元素。如果一個插入式註解處理器修改了抽象語法樹,則在修改語法樹之後回到解析與填充符號表的過程重新處理。

  • 分析與生成字節碼

    這個過程主要對生成的抽象語法樹進行語義分析,而後生成所需的字節碼。語義分析具體分可以分為四個步驟:
    • 標註檢查
      標註檢查包括:變量使用前是否聲明、變量類型是否匹配等。
      標註檢查還包括一個重要的優化行為——常量折疊:
      int a = 1 + 2; 會被優化成 int a = 3;
    • 數據與控制流分析
      數據與控制流分析是用於檢查程序的上下文邏輯是否正確,包括:方法是否每條執行路徑都有返回值、異常是否被拋出或者被catch等。
    • 解語法糖
      Java提供了很多語法糖,常見的如:泛型、自動裝箱拆箱、變長參數、for-each循環、斷言語句等。這些語法糖在編譯期都會被還原成簡單的基礎語法。
    • 字節碼生成
      字節碼生成即將前面幾個步驟生成的信息轉換成字節碼生成Class文件。
      在這個過程中,編譯器會自動生成<init>方法和<clinit>方法插入語法樹。
      編譯器將實例變量的初始化、語句塊、調用父類實例構造器等操作整理生成類的實例構造方法<init>。將static變量的初始化、static語句塊等操作整理生成類的構造方法<clinit>



參考資料:《深入理解Java虛擬機》

Java編譯期的前端過程