標籤:匹配 遍曆 抽象文法樹 很多 mpi 處理 後序遍曆 builder tools
要在JVM中執行java代碼必須要編譯為class檔案,JDK是如何將Java代碼編譯為class檔案,這種機制通常被稱為Java源碼編譯機制。
1、JVM定義了class檔案的格式,但是並沒有定義如何將java源碼編譯為class檔案,各個廠商在實現JDK時候通常會將符合java語言規範的源碼編譯為class檔案的編譯器,如JDK就是javac
javac編譯產生class檔案的步驟如下:
1、分析和輸入到符號表 (Parse and Enter )
Parse過程所做的為詞法和文法分析,詞法分析(com.sun.tools.javac.parser.Scanner)要完成的是將代碼字串轉變為token序列(例如Token.EQ(name:=));文法分析(com.sun.tools.javac.parser.Parser)要完成的是根據文法由token序列產生抽象文法樹。
Enter(com.sun,tools,javac.comp.Enter)過程為將符號輸入到符號表,通常包括確定類的超類型和介面,根據需要添加預設構造器,將類中出現的符號輸入類自身的符號表中等。
2、註解處理(Annotation Processing)
該步驟主要用於處理使用者自定的Annotation,可能帶來的好處是基於annotation來產生附加的代碼或進行一些特殊的檢查,從而節省一些共用的代碼的編寫,例如當採用Lombok時,可大大減少代碼量,編譯是引入Lombok對實體進行編譯後,再通過javap查看class檔案,發現自動成get set toString等方法,此功能基於JSR269,在JDK1.6中提供支援,在Annotation Processing進行後,再次進入Parse and Enter步驟
3、語義分析和產生class檔案(Analyse and Generate)
Analyse步驟基於抽象文法樹進行一系列的文法分析,包括將文法樹中的名字,運算式等元素與變數,方法,類型等聯絡在一起,檢查變數使用前是否聲明,推導泛型方法的型別參數,檢查類型匹配性,進行常量摺疊;檢查所有語句都可到達,檢查所有checked exception都被捕捉或者拋出,檢查變數的確定性賦值(如有傳回值的方法必須定有傳回值);檢查變數的確定性不重複賦值(例如聲明為final的變數);解除文法糖(消除if(false) )形式的無用代碼;將泛型Java轉為普通的Java,將含有文法糖的文法樹改為含有簡單語言結構的文法樹,例如for each迴圈,自動裝箱,拆箱等
在完成語義解析後,開始產生class檔案(com.sun.tools.javac.jvm.Gen)產生的步驟,首先將執行個體成員初始化器手機到構造器中,將靜態成員初始化器手機為<cinit>();接著將抽象文法樹產生位元組碼,採用的方法為後序遍曆文法樹,並進行最後的少量代碼轉換(例如String相加轉變為StringBuilder操作);最後從符號表產生class檔案。
產生class檔案除了javac之外,還可以通過ECJ(Eclipse compiler for java) 或者是Jikes等編譯器來將Java源碼編譯為class檔案。
class檔案不僅僅存放了位元組碼,還存放了很多輔助JVM來執行class的附加資訊,一個class檔案包括
-結構資訊
包括class檔案格式版本號碼及各部分的數量和大小資訊
-中繼資料
簡單的說可以認為是方法資訊對用的java源碼中語句,運算式對應的資訊,主要有位元組碼,異常處理表,求值棧與局部變數區大小,求值棧的類型記錄,調試用符號資訊。
【java】之java代碼的執行機制