Javac 編譯器

要點:

1、Javac 如何將 Java 的源代碼轉化爲 class 字節碼?
2、Javac 的語法樹結構;
3、Javac 的詳細工作流程;
4、Java 中如何實現內部類?
5、Javac 與其他編譯器的比較;

1 什麼是 Javac ?

Javac 是一種編譯器,其作用是將 Java 源程序 編譯成符合 JVM 規範的 Java 字節碼(即 JVM 可以解釋執行的二進制碼)

2 Javac 的基本結構

Javac 主要的四個模塊:

詞法分析器組件:從源代碼中識別出哪些字節是我們定義的語法關鍵字,如 if、else、for 等等。
語法分析器組件:形成一個符合 JVM 規範的抽象語法樹。(抽象語法樹是一個結構化的語法表達形式,作用是把語言的主要詞法用一個結構化的形式組織在一起)
語義分析器組件:主要作用是將複雜的語法轉化成更簡單的語法
字節碼生成器組件:根據經過註解的抽象語法樹生成字節碼

3 Javac 工作原理分析

詞法分析器:
這個過程在 JavacParser 的 ParseCompilationUnit 方法中完成的,它的源代碼可以通過 OpenJDK 下載來查看。該方法從源文件的第一個字符開始,逐個字符的檢查,按照 Java 語法規範依次找出 package、import、類定義、以及屬性和方法定義等,將這個類中的所有關鍵詞匹配到Token類的所有項中的任何一項,即將Java源文件的字符流轉變爲對應的Token流,最後構建一個抽象語法樹。

語法分析器:
將詞法分析器分析的 Token 流組建成更加結構化的語法樹,也就是將一個個單詞組裝成一句話,一個完整句子。具體一點說就是按照一定的規則逐個地解析 Token 流中的每一項,每個語法樹上的節點都是 com.sun.tools.javac.tree.JCTree 的一個實例。

語義分析器:
在這課語法樹上再進行一些處理以產生Java字節碼。如給類添加默認的構造函數、檢查變量在使用之前是否已經初始化、將一些常量進行合併處理、檢查操作變量類型是否匹配、檢查所有操作語法是否可達、檢查異常是否捕獲或擲出等。最後得到完善的最終的語法樹。

代碼生成器:
遍歷最終語法樹生成 Java 字節碼,這步通過 com.sun.tools.javac.jvm.Gen 這個類來完成。生成字節碼需要進過兩步:首先將 Java 方法中的代碼塊轉成符合 JVM 語法樹的命令形式,JVM 的操作都是基於棧的,所有操作都必須經過出棧和進棧來完成。然後,按照 JVM 的文件組織格式將字節碼輸出到以 class 爲擴展名的文件中。

4 訪問者模式

4.1 設計初衷:

將穩定的數據結構和對數據結構的操作解耦。

4.2 訪問者模式中包含的角色:

抽象訪問者(Visitor)
具體訪問者(ConcreteVisitor)
抽象節點元素(Element)
具體節點元素(ConcreteElement)
結構對象(ObjectStructure):它持有整個 抽象語法樹,它提供一個接口。客戶端 調用 訪問者 ,通過這個接口就能訪問到 節點元素。
客戶端(Client)

4.3 Javac 中訪問者模式的實現

(1)Javac 中哪裏用到了訪問者模式?
Javac 的四個主要模塊中有很多遍歷抽象語法樹的過程。訪問抽象語法樹的節點元素的過程就是一個訪問者模式。

(2)Javac 中使用訪問者模式有什麼好處?
訪問者模式可以將 抽象語法樹 和 對抽象語法樹的操作 解耦,從而使得增加對抽象語法樹的操作,而不需要去修改 抽象語法樹,也不必修改以前 對抽象語法樹的操作,只要執行時再定義新的 訪問者 就行了。

(3)訪問者是如何訪問 抽象語法樹的節點元素的?
客戶端 調用 訪問者 ,通過結構對象提供的接口就能訪問到 節點元素。

(4)爲什麼不同的訪問者訪問同一套數據結構(Javac 中是抽象語法樹),而訪問者的行爲卻各自不同?
遍歷抽象語法樹使用統一的 accept 接口,每個節點元素都會實現這個接口,但是不同的節點元素的 accept 實現是不同的,所以不同的訪問者訪問不同的節點元素就會得到不同的結果。

參考書籍:
《深入分析 JavaWeb 技術內幕》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章