Java編譯期優化思惟導圖
![編譯期優化 編譯期優化](http://static.javashuo.com/static/loading.gif)
本文參考自來自周志明《深刻理解Java虛擬機(第2版)》,拓展內容建議讀者能夠閱讀下這本書。
文字版以下:java
編譯期優化
javac的編譯過程
解析和填充符號表
-
解析 Parse數組
-
詞法分析app
- 源代碼字符流 -> 標記Token
- 源代碼字符是程序編寫的最小單位,Token是編譯過程的最小元素不可再分
-
語法分析優化
- Token序列 -> 抽象語法樹AST
- AST描述代碼語法結構的樹狀結構,每一個節點表示一個語法結構(包、類型、修飾符、運算符、接口、返回值、註釋等)
-
填充符號表 Enterui
- 符號表 -> 待處理列表To Do list
- 符號表symbol table是由一組符號地址和符號信息構成的表
- 包、類、方法、字段均可以抽象成一個符號(symbol),不一樣種類的符號之間能夠有包含嵌套關係,這一階段的任務就是識別出各種符號,並對不一樣種類的符號按照包含嵌套關係進行歸類,並掛接到AST對應的結點上。
插入式註解處理器的註解處理
- 使用JDK1.6後提供的插入式註解標準API來開發,這些API用於讀取、修改、添加語法樹的元素,運行時使用-processor參數來參與javac的編譯
- 插入式註解處理器起編譯期插件做用
- 在編譯期間插入式註解處理器對註解進行處理,能夠讀取、修改、添加語法樹的元素
- 若是處理過程當中修改了語法樹將會觸發編譯期回到填充符號表階段從新處理一輪(Round),直到語法樹再也不變化
- 實例:lombok,在設置了相關注解後lombok會在編譯期生成源代碼中沒有的方法等
分析與字節碼生成
-
語義分析spa
-
標註檢查插件
- 變量使用前是否已經被聲明
- 變量與賦值之間的數據類型是否可以匹配
- 常量摺疊
- …
-
數據及控制流檢查對象
- 程序局部變量在使用前是否有賦值
- 方法的每條路徑是否都有返回值
- 是否全部的受檢異常都被正確處理
-
final參數、final局部變量是否被修改接口
- 局部變量是否用final修飾最終在class文件中是無差異的,由於局部變量在class中是沒有訪問標誌的,這個final不變性只在編譯期檢查時保證
- …
-
解語法糖資源
- 泛型:編譯後發生類型擦除,可是編譯信息會保留Signature
- 變長參數:編譯後變成數組類型的參數
- 自動裝箱拆箱:編譯後裝箱經過valueOf()變成了對象,拆箱經過xxxValue()變成了原始類型值
- 遍歷循環:編譯後變成了迭代器遍歷
- 條件編譯:編譯後將常量不可達條件分支直接消除掉
- 內部類
- 枚舉類
- 斷言
- switch處理枚舉和字符串
- try定義和關閉資源
-
字節碼生成
- 處理完的語法樹和符號表 -> 字節碼
-
少許的代碼添加和轉換工做
-
添加<init>()和<clinit>()方法
-
<init>()收斂的操做
- 調用父類的<init>()
- 執行{}語句塊
- 初始化實例變量
- <init>()是字節碼級別的方法,對使用者是透明的,與每一個<init>()對應的構造方法是源碼級別的方法,是真正被使用者開放的。<init>()和構造方法一一對應,是同一律念在兩個級別的含義
-
<clinit>()收斂的操做
- (JVM自動保證執行父類的<clinit>())
- 執行static{}語句塊
- 初始化類變量
- 字符串加操做替換爲StringBuffer或StringBuilder的append()操做
歡迎關注本站公眾號,獲取更多信息