咱們都知道 *.java 文件要首先被編譯成 *.class 文件才能被 JVM 認識,這部分的工做主要由 Javac 來完成,相似於 Javac 這樣的咱們稱之爲前端編譯器;前端
可是 *.class 文件也不是機器語言,怎麼才能讓機器識別呢?就須要 JVM 將 *.class 文件編譯成機器碼,這部分工做由JIT 編譯器完成;java
除了這兩種編譯器,還有一種直接把 *.java 文件編譯成本地機器碼的編譯器,咱們稱之AOT 編譯器。git
首先,咱們先導一份 javac 的源碼(基於 openjdk8)出來,下載地址:https://hg.openjdk.java.net/jdk8/jdk8/langtools/archive/tip.tar.gz,而後將 JDK_SRC_HOME/langtools/src/share/classes/com/sun 目錄下的源文件所有複製到工程的源碼目錄中,生成的 目錄 以下:
github
咱們執行 com.sun.tools.javac.Main 的 main 方法,就和咱們在命令窗口中使用 javac 命令同樣:
ui
從 Sun Javac 的代碼來看,編譯過程大體能夠分爲三個步驟:.net
這三個步驟所作的工做內容大體以下:blog
這三個步驟之間的關係和交互順序以下圖所示,能夠看到若是註解處理器在處理註解期間對語法樹進行了修改,編譯器將回到解析和填充符號表的過程進行從新處理,直到註解處理器沒有再對語法樹進行修改成止。ip
Javac 編譯的入口是 com.sun.tools.javac.main.JavaCompiler 類,上述三個步驟的代碼都集中在這個類的 compile() 和 compile2() 中:get