早期(編譯期)優(yōu)化
前端編譯器(把*.java文件轉(zhuǎn)變成*.class文件):Sun的Javac、 Eclipse JDT中的增量式編譯器(ECJ)。
JIT編譯器(把字節(jié)碼轉(zhuǎn)變成機(jī)器碼):HotSpot VM的C1、 C2編譯器。
AOT編譯器(把*.java文件編譯成本地機(jī)器代碼):GNU Compiler for the Java(GCJ)、 Excelsior JET。
Javac編譯器
編譯過程大致分為三個:解析與填充符號表過程、插入式注解處理器的注解處理過程、分析與字節(jié)碼生成過程。
- 解析與填充符號表過程
- 1.詞法、 語法分析
- 詞法分析是將源代碼的字符流轉(zhuǎn)變?yōu)闃?biāo)記(Token)集合
-
語法分析是根據(jù)Token序列構(gòu)造抽象語法樹的過程,抽象語法樹(Abstract Syntax Tree,AST)是一種用來描述程序代碼語法結(jié)構(gòu)的樹形表示方式,語法樹的每一個節(jié)點(diǎn)都代表著程序代碼中的一個語法結(jié)構(gòu)(Construct)
圖1 Javac編譯過程
- 2.填充符號表
- 符號表(Symbol Table)是由一組符號地址和符號信息構(gòu)成的表格
- 1.詞法、 語法分析
- 注解處理器
- 如果插入式注解處理器在處理注解期間對語法樹進(jìn)行了修改,編譯器將回到解析及填充符號表的過程重新處理,直到所有插入式注解處理器都沒有再對語法樹進(jìn)行修改為止,如圖1的回環(huán)過程(Round)。
- 語義分析與字節(jié)碼生成
- 語義分析的主要任務(wù)是對結(jié)構(gòu)上正確的源程序進(jìn)行上下文有關(guān)性質(zhì)的審查,如進(jìn)行類型檢查。
- 語義分析過程分為標(biāo)注檢查以及數(shù)據(jù)及控制流分析
- 1.標(biāo)注檢查
- 檢查的內(nèi)容包括諸如變量使用前是否已被聲明、 變量與賦值之間的數(shù)據(jù)類型是否能夠匹配等
- 2.數(shù)據(jù)及控制流分析
- 對程序上下文邏輯更進(jìn)一步的驗(yàn)證,它可以檢查出諸如程序局部變量在使用前是否有賦值、 方法的每條路徑是否都有返回值、 是否所有的受查異常都被正確處理了等問題。
- 1.標(biāo)注檢查
- 局部變量與字段(實(shí)例變量、 類變量)是有區(qū)別的,它在常量池中沒有
CONSTANT_Fieldref_info的符號引用,自然就沒有訪問標(biāo)志(Access_Flags)的信息,甚至可能連名稱都不會保留下來(取決于編譯時的選項(xiàng)),自然在Class文件中不可能知道一個局部變量是不是聲明為final- 3.解語法糖
- 語法糖指指在計算機(jī)語言中添加的某種語法,這種語法對語言的功能并沒有影響,但是更方便程序員使用。
- 虛擬機(jī)運(yùn)行時不支持泛型、變長參數(shù)等語法,它們在編譯階段還原回簡單的基礎(chǔ)語法結(jié)構(gòu),這個過程稱為解語法糖。
- 4.字節(jié)碼生成
- 字節(jié)碼生成階段不僅僅是把前面各個步驟所生成的信息(語法樹、 符號表)轉(zhuǎn)化成字節(jié)碼寫到磁盤中,編譯器還進(jìn)行了少量的代碼添加和轉(zhuǎn)換工作。
- 實(shí)例構(gòu)造器<init>()方法和類構(gòu)造器<clinit>()方法就是在這個階段添加到語法樹之中的
- 3.解語法糖
Java語法糖
泛型與類型擦除
泛型技術(shù)實(shí)際上是Java語言的一顆語法糖,Java語言中的泛型實(shí)現(xiàn)方法稱為類型擦除,基于這種方法實(shí)現(xiàn)的泛型稱為偽泛型。
