为啥要看javac源代码
前言
本文為javac 源碼解析的第一篇,主要介紹了如下內如:
- 閱讀javac源代碼的好處
- 閱讀javac源代碼的儲配知識
- build javac
- javac源代碼結構說明
重要說明: javac是java的編譯器,內容高深,非常人所能參透,本人也同樣,寫本文只為了交流,因此,諸位看客發現紕漏,請指出,點撥一下小弟,不甚感激.
閱讀javac源代碼的好處
閱讀javac的好處如下:
- 能接觸java的真實面貌
- 能更早的進入到java大神的行列
- 能夠獲取到更多面試機會
閱讀javac源代碼的儲配知識
按照官方的說法是: javac讀取按照java語法寫成的源文件,同時生產字節碼文件.其中java語法被The Java Language Specification (JLS) 所定義,字節碼文件則被The Java Virtual Machine Specification (JVMS) 所定義. 同時,該編譯器會處理注解,這是被Pluggable Annotation Processing API (JSR 269). 所定義的. 同樣,該編譯器還支持 the Java Compiler API (JSR 199). 因此,閱讀javac所需要的知識也就很明白了:
另外,既然是一個編譯器,自然逃不過編譯原理的范疇.
build javac
javac的源代碼可以在如下地址中找到: javac源代碼.下載下來后,按照 官方說明build說明 進行build即可.
不過,我這里采用的是build jdk的方式構建的.現說明如下:
由于本人是在mac 上進行構建的,因此需要對源碼做如下修改:
在hotspot/src/share/vm/code/relocInfo.hpp 中,將 datalen = 0 改為 datalen. 如圖所示:
搜索 int datalen, 第 462 行,改為 int datalen = 0.如圖所示:
在hotspot/src/share/vm/opto/loopPredicate.cpp中,將 _igvn.type(rng)->is_int() >= 0 改成 _igvn.type(rng)->is_int()->_lo >= 0 如圖所示:
在hotspot/src/share/vm/runtime/virtualspace.cpp中,將 base() > 0 改成 base() != 0 如圖所示:
修改 nashorn/make/BuildNashorn.gmk 中的 第 80 行 -cp 修改為 -Xbootclasspath/p . 如圖所示:
然后,創建一個 envsetup.sh, 內容如下:
\# 設定語言選項,必須設置 export LANG=C \# Mac平臺,C編譯器不再是GCC,是clang export CC=gcc \# 跳過clang的一些嚴格的語法檢查,不然會將N多的警告作為Error export COMPILER_WARNINGS_FATAL=false \# 鏈接時使用的參數 export LFLAGS='-Xlinker -lstdc++' \# 是否使用clang export USE_CLANG=true \# 使用64位數據模型 export LP64=1 \# 告訴編譯平臺是64位,不然會按32位來編譯 export ARCH_DATA_MODEL=64 \# 允許自動下載依賴 export ALLOW_DOWNLOADS=true \# 并行編譯的線程數,編譯時間長,為了不影響其他工作,我選擇為2 export HOTSPOT_BUILD_JOBS=2 export ALT_PARALLEL_COMPILE_JOBS=2 \# 是否跳過與先前版本的比較 export SKIP_COMPARE_IMAGES=true \# 是否使用預編譯頭文件,加快編譯速度 export USE_PRECOMPILED_HEADER=true \# 是否使用增量編譯 export INCREMENTAL_BUILD=true \# 編譯內容 export BUILD_LANGTOOLS=true export BUILD_JAXP=false export BUILD_JAXWS=false export BUILD_CORBA=false export BUILD_HOTSPOT=true export BUILD_JDK=true \# 編譯版本 export SKIP_DEBUG_BUILD=true export SKIP_FASTDEBUG_BUILD=false export DEBUG_NAME=debug \# 避開javaws和瀏覽器Java插件之類的部分的build export BUILD_DEPLOY=false export BUILD_INSTALL=false \# 加上產生調試信息時需要的 objcopy export OBJCOPY=gobjcopy然后,執行 source envsetup.sh
進行build。
執行如下命令:
bash ./configure \ --with-target-bits=64 \ --with-debug-level=slowdebug --enable-debug-symbols \ ZIP_DEBUGINFO_FILES=0執行命令:
make all至此,就會看到build 成功的輸出
進行測試,如圖所示:
添加編譯的jdk到eclipse中,如圖所示:
創建一個java 項目,使用我們自己build的jdk.然后將javac的源代碼賦值到該項目中, javac的源代碼在 openjdk/langtools/src/share/classes/com/sun/tools 下.導入后,如圖所示:
寫兩個類進行測試,代碼如下:
import com.sun.tools.javac.main.Main; public class DebugEntryPoint {public static void main(String[] args) {Main m = new Main("fx_debug");m.compile(asArray("/Users/xxxxx/Documents/2017-03-22-brabch/javac-test/src/Demo.java"));}private static <T> T[] asArray(T... args) {return args;} } public class Demo {public void foo() {char a = 'a';a += 32; // 可以通過} }執行后,就可以看到會生成 Demo.class
javac源代碼結構說明
用官方的一張圖進行說明:
在com.sun.tools.javac下有如下幾個包,現說明如下:
1. api –> 實現了JavaCompiler 和javax.tools中其他的api
2. code –> 定義了Java程序的語義元素的表示,如符號、作用域和類型,在javax.lang.model.*.中實現.
3.comp –> 編譯器的主要處理階段,如標記、流分析、“解語法糖”和擦除
4. file –> 使用java.nio.file 的api來訪問本地的文件系統.
5. jvm –> 讀取和寫class文件,生成字節碼
6. main –> 編譯的主要驅動代碼,提供了多樣的編譯步驟選項
7.model –> javax.lang.model.*. 的額外實現類
8.parser –> 讀取java源文件生成語法樹
9.processing –> 實現了在javax.annotation.processing.*定義的api
10.resources –> 信息本地化和版本信息的資源文件
11. tree –> 編譯器的語法樹的表示和實用類,實現了com.sun.source.*.中定義的api
12. util –> 工具類
參考鏈接
compiler-package-overview
compiler-README.html#build
compiler-index
在 macOS 上編譯 OpenJDK 8
如何構建javac的調試環境
總結
以上是生活随笔為你收集整理的为啥要看javac源代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSIG基础研究岗腾讯面试经验
- 下一篇: 全面反攻,不给割肉者任何机会