【轉】JDK的Parser來解析Java原始碼詳解
轉自:https://www.jb51.net/article/92989.htm
這篇文章主要介紹了JDK的Parser來解析Java原始碼的相關資料,需要的朋友可以參考下
在JDK中,自帶了一套相關的編譯API,可以在Java中發起編譯流程,解析Java原始檔然後獲取其語法樹,在JDK的tools.jar(OSX下可以在/Library/Java/JavaVirtualMachines/jdk_version/Contents/Home/lib中找到)中包含著這整套API,但是這卻不是Oracle和OpenJDK釋出中的公開API,因此對於這套API,並沒有官方的正式文件來進行說明。但是,也有不少專案利用了這套API來做了不少事情,例如大名鼎鼎的lombok使用了這套API在Annotation Processing階段修改了原始碼中的語法樹,最終結果相當於直接在原始檔中插入了新的程式碼!
由於這套API目前缺少相關文件,使用起來比較困難,例如,解析原始碼中的所有變數,並打印出來:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
"User.java" ;
new JavacTool();
|
其中 User.java的程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
執行上面的JavaParser結果如下:
1 2 3 |
|
這裡我們是首先通過JavaCompiler.CompilationTask解析了原始檔之後,再使用自定義的SourceVisitor(繼承自TreeScanner)來對原始碼的結構進行訪問,在SourceVisitor類中,通過過載visitVariable來對一個編譯單元(單個原始碼檔案)進行解析,訪問其中的所有的變數,這裡可以看出,我們沒有辦法拿到這個變數型別的全限定名(包含包名),只能拿到的對應的簡單名字,因此,型別的確定需要外部實現自行確定,例如可以通過記錄類所在的包名,遞迴的搜尋整個原始碼目錄來跟蹤所有類的全限定名,查詢import中是否包含對應的型別等。
TreeScanner中除了visitVariable方法外,還包含了大量其他的visitXYZ方法,例如,可以遍歷所有的import,方法定義,Annotation等,更具體可以檢視OpenJDK中關於這個的原始碼
這裡再來看下另外一個例子,過載visitClass方法,訪問所有的內部類以及類本身:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
這裡簡單的列印了類名以及變數的名稱,型別,annotation型別,執行上面的程式碼,結果如下:
1 2 3 4 5 |
|
可以看出我們把類名以及類中的變數都列印了出來。而在visitClass方法中,我們可以通過getMembers方法拿到類中所有的成員,包括變數,方法,annotation等,分別對應著不同的型別,例如變數就對應著VariableTree型別,方法就對應的MethodTree型別。
總得來說,雖然實際上使用並不算特別複雜,但是由於缺少文件,對使用造成了很大的障礙,而且目前所介紹的只是這套API的一少部分,後續我將會繼續研究這套API的相關函式。
以上就是對JDK的Parser來解析Java原始碼 的資料整理,後續繼續補充相關資料,謝謝大家對本站的支援!