首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Javac 編譯器四大核心階段深度解析:從原始碼到位元組碼

     編輯:Java 綜合教學

編譯流程總覽

Javac(com.sun.tools.javac.main.JavaCompiler)將 .java 轉為 .class,歷經四大階段:

  1. 詞法分析 → Token 流
  2. 語法分析 → 抽象語法樹 (AST)
  3. 語義分析 → 註解檢查、資料流/控制流分析、解語法糖
  4. 位元組碼生成 → .class 檔案

階段一:詞法分析

  • 輸入:字元流
  • 輸出:Token 序列(關鍵字、識別符、字面常數、運算子等)
  • 實現類:com.sun.tools.javac.parser.Scanner
  • 例子:int a = b + 2; → INT, IDENTIFIER(a), ASSIGN, IDENTIFIER(b), PLUS, INT_LITERAL(2), SEMICOLON

階段二:語法分析

  • 任務:依 Java 語法規則將 Token 組裝成樹狀結構
  • 產出:JCTree 節點構成的 AST,每個節點對應一個語法結構(類、方法、運算式、註解等)
  • 實現類:com.sun.tools.javac.parser.Parser
  • 關鍵點:此階段後編譯器不再直接操作原始碼,所有後續處理皆基於 AST

階段三:語義分析 —— 最複雜、最核心

分為三個子階段,入口均在 com.sun.tools.javac.comp 套件:

1. 填充符號表

  • 實現:Enter 類
  • 工作:遍歷 AST,將類名、方法名、欄位名等註冊到符號表(Symbol 物件),同時自動補齊預設建構子
  • 跨類引用解析:遇到外部類型時遞迴解析對應 .class 或 .java

2. 註解檢查

  • 實現:Attr(屬性賦值)+ Check(邏輯檢查)
  • 核心檢查項:
    • 型別相容性、變數初始化檢查
    • 泛型型別推導
    • 常數摺疊:int a = 1 + 2; → AST 直接保留 3
    • Checked Exception 捕獲/拋出驗證
    • 可達性分析(return 後無死碼)

3. 資料流與控制流分析

  • 入口:Flow 類
  • 資料流:最終賦值檢查、final 欄位單一賦值、方法回傳型別確定性
  • 控制流:
    • 死碼消除(if(false) 區塊)
    • 自動裝箱/拆箱插入
    • 解語法糖:內部類、Lambda、try-with-resources、foreach、switch 字串等 → desugar() 在 TransTypes、Lower 中完成

階段四:位元組碼生成

  • 實現:com.sun.tools.javac.jvm.Gen
  • 兩步走:
    1. 將方法程式碼轉為基於運算堆疊的 JVM 指令序列
    2. 依 Class 檔案格式規範輸出 .class(含常數池、方法表、屬性表等)
  • 隱藏動作:實例建構器(<init>)與類建構器(<clinit>)在此階段注入 AST

註解處理器擴展機制

JDK 6+ 引入 JSR 269(javax.annotation.processing),允許在填充符號表之後、註解檢查之前介入:

  • 處理器可讀取/修改/新增 AST 節點
  • 若修改了 AST,編譯器回滾至「解析與填充符號表」重新開始,直到所有處理器不再修改為止
  • 典型應用:Lombok、MapStruct、Dagger 編譯期程式碼生成
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved