>[info] 平臺無關性:一次編譯,到處運行
>[] 我對『Compile once, run anywhere』這個宣傳語提出的歷史背景非常感興趣。這個宣傳語似乎在暗示 C 語言有一個缺點:對于每一個不同的平臺,源代碼都要被編譯一次。我不解的地方是,為什么這會是一個問題?不同的平臺,可執行的機器碼必然是不一樣的。源代碼自然需要依據不同的平臺分別被編譯。 我覺得真正問題不在編譯這一塊,而是在 C 語言源文件這一塊。我沒有 C 語言的編程經驗,但是似乎 C 語言程序經常需要調用操作系統層面的 API。不同的操作系統,API 一般不同。為了支持多平臺,C 語言程序的源文件需要根據不同平臺修改多次。這應該是一個非常大的痛點。我回頭查了一下當時的宣傳語,原文是『Write once, run anywhere』,焦點似乎并不在編譯上,而是在對源文件的修改上。
>[warning] GC:垃圾回收機制
>[success] 語言特性:泛型、反射、`lamuda`表達式表達式
>[danger]面向對象:封裝、繼承、多態
>[info]類庫:集合、并發、網絡、`IO/NIO`
>[success] Jva半編譯半解釋機制
>[] 眾所周知,我們通常把`Java`分為編譯期和運行時。這里說的`Java`的編譯和`C/C++`是有著不同的意義的,`Javac`的編譯,編譯`Java`源碼生成`“.class”`文件里面實際是字節碼,而不是可以直接執行的機器碼。`Java`通過字節碼和`Java`虛擬機`(JVM)`這種跨平臺的抽象,屏蔽了操作系統和硬件的細節,這也是實現“一次編譯,到處執行”的基礎。
在運行時,`JVM`會通過類加載器`(Class-Loader)`加載字節碼,解釋或者編譯執行。就像我前面提到的,主流`Java`版本中,如`JDK 8`實際是解釋和編譯混合的一種模式,即所謂的混合模式`(\-Xmixed)`。通常運行在`server`模式的`JVM`,會進行上萬次調用以收集足夠的信息進行高效的編譯,`client`模式這個門限是1500次。`Oracle Hotspot JVM`內置了兩個不同的`JIT compiler`,`C1`對應前面說的`client`模式,適用于對于啟動速度敏感的應用,比如普通`Java`桌面應用;`C2`對應`server`模式,它的優化是為長時間運行的服務器端應用設計的。
默認是采用所謂的分層編譯`(TieredCompilation)`。這里不再展開更多`JIT`的細節,沒必要一下子就鉆進去,我會在后面介紹分層編譯的內容。
Java虛擬機啟動時,可以指定不同的參數對運行模式進行選擇。 比如,指定`“-Xint”`,就是告訴`JVM`只進行解釋執行,不對代碼進行編譯,這種模式拋棄了`JIT`可能帶來的性能優勢。
畢竟解釋器`(interpreter)`是逐條讀入,逐條解釋運行的。與其相對應的,還有一個`“-Xcomp”`參數,這是告訴`JVM`關閉解釋器,不要進行解釋執行,或者叫作最大優化級別。那你可能會問這種模式是不是最高效啊?簡單說,還真未必。`“-Xcomp”`會導致`JVM`啟動變慢非常多,同時有些`JIT`編譯器優化方式,比如分支預測,如果不進行`profling`,往往并不能進行有效優化。
除了我們日常最常見的`Java`使用模式,其實還有一種新的編譯方式,即所謂的`AOT(Ahead-of-Time Compilation)`,直接將字節碼編譯成機器代碼,這樣就避免了`JIT`預熱等各方面的開銷,比如`Oracle JDK 9`就引入了實驗性的`AOT`特性,并且增加了新的`jaotc`工具。利用下面的命令把某個類或者某個模塊編譯成為`AOT`庫。
`jaotc --output libHelloWorld.so HelloWorld.class`
`jaotc --output libjava.base.so --module java.base`
然后,在啟動時直接指定就可以了。
`java -XX:AOTLibrary=./libHelloWorld.so,./libjava.base.so HelloWorld`
而且,`Oracle JDK`支持分層編譯和`AOT`協作使用,這兩者并不是二選一的關系。如果你有興趣,可以參考相關文檔:http://openjdk.java.net/jeps/295。`AOT`也不僅僅是只有這一種方式,業界早就有第三方工具(如`GCJ、Excelsior JET`)提供相關功能。
另外,`JVM`作為一個強大的平臺,不僅僅只有`Java`語言可以運行在`JVM`上,本質上合規的字節碼都可以運行,`Java`語言自身也為此提供了便利,我們可以看到類似`Clojure`、`Scala`、`Groovy`、`JRuby`、`Jython`等大量`JVM`語言,活躍在不同的場景。