《OracleJRockit:TheDefinitiveGuide》一書是由OracleJRockit的兩位資深開發人員寫的,其中的MarcusHirt更是JRockitMissionControl的leader,這本書詳細的對OracleJRockit進行了介紹,最突出的特色很是系統化的介紹了一個JVM一般是如何實現的,而JRockit這樣一個極爲優秀的JVM又是作了哪些優化,爲何作這些優化,這本書對於對JVM感興趣的同窗而言應該是必讀的一本書,其實即便對於JVM興趣不強的同窗,裏面的優化思路的介紹也是值得學習,本系列的blog主要是總結看這本書獲得的一些收穫,因爲書中知識量巨大,所以得分紅多篇blog來總結了。java
書的第二章爲:AdaptiveCodeGeneration,在這章中做者向咱們講解了一個優秀的JVM是如何來實現代碼的高效執行的,感興趣的同窗其實能夠在不看下面blog內容以前,先考慮下若是是你作的話,你會怎麼作來實現Java代碼的高效執行呢,而後再對比下這章的內容,我想你能學到不少的,:)ide
用過Java的同窗都知道,Java是經過javac將Java源碼編譯爲class文件,而後經過ClassLoader裝載此class文件,以後就可執行此class了,要最高效的執行這個class,最好的方法莫過於class文件直接就是機器碼,這樣直接執行就能夠了,但Java是跨平臺的,所以class文件就不能是機器碼了。性能
因爲class文件不是直接的機器碼,要執行它最簡單的方法就是採用純粹的解釋方式,解釋方式因爲每次都得將class文件中的指令翻譯爲對應的機器環境的指令,效率是很低的。學習
爲了能更高效的執行,同時又保持跨平臺的特性,另一個方法就是在執行class時再將其翻譯爲對應的機器碼,這個方法是比較靠譜的,所以不管是Hotspot、仍是JRockit,都採用了這種方式,也就是你們熟知的JIT(JustInTime)Compiler。優化
OK,既然以爲在裝載class後翻譯成機器碼去執行能夠比較高效,那這個時候又會出現兩種情況,是執行class的時候就馬上翻譯成機器碼,仍是先用解釋模式執行,而後到必定時機再翻譯成機器碼呢,之因此出現這兩種情況,緣由在於將class翻譯爲機器碼是須要消耗時間的,所以若是執行class的時候就馬上翻譯成機器碼的話,也就會致使Java程序啓動速度會比較慢,JRockit是這麼認爲的,JRockit的服務對象是server級應用,這類應用的特色是沒那麼在意啓動速度,而更在意的是執行時的高效,並且若是執行的時候就馬上翻譯成機器碼的話,就意味着壓根不須要實現解釋器,所以JRockit採起的方法是在執行class時直接編譯爲機器碼,而Hotspot因爲須要同時支持client和server應用,對於client應用而言,啓動速度很是重要,所以Hotspot採用的是先解釋執行,到了必定時機後再翻譯成機器碼。ui
若是認爲就這樣就完成了Java代碼的執行的實現,那就過小看JVM了,因爲JVM可以知道代碼運行的所有情況,天然還能夠作出更多更出色的提高代碼執行速度的優化,例如標量替換、更好的inline等,後面再來細說,所以這樣就出現了一個情況,何時對哪些代碼來作這些更猛的優化呢。線程
真正值得作更猛的優化的代碼天然是所謂的」熱點」代碼,如何來發現哪些代碼是熱點代碼呢,一般有三種方法:
一、方法調用計數器
方法調用計數器是常見的方式,hotspot採用的即爲這種,這種方式很差的地方就在於計數器自己常常是cpucachemisses的,所以稍微會有點影響性能。
二、對線程進行採樣
可採用軟件或硬件方式來實現,軟件方式實現很差的地方在於採樣的時候須要暫停線程,好處是由於是採樣,不須要對全部方法進行計數,硬件方式天然是最好的,但不是全部的硬件都支持的,支持的硬件中最典型的是intelIA-64的CPU。翻譯
在有了發現熱點代碼的方法後,接下來須要作的就是更猛的優化,有不少種,例如Java的代碼中,一般會是接口方式的調用,但由於是接口方式的調用,因此其實默認狀況下是很差作inline處理的,但JVM爲了更高效的執行代碼,如發現這代碼爲熱點代碼,那麼就會作一些激進的優化,例如會假設這個接口只有一個實現,而後就能夠直接將此實現對應的代碼inline進來了(至於爲何inline後效率更高,這個請參考編譯原理之類的書),這些激進優化一樣適合於if、拋異常這些情況,固然,當激進優化的條件失效時,就會逆優化回到以前基本編譯的代碼。
而其餘的更猛的優化還包括根據線程執行路徑進行逃逸分析等,後面再專門寫一篇blog來說解下一些翻譯爲機器碼的優化吧,其實大多都是編譯原理的一些東西。code
書中在介紹JRockit如何實現本身的JITCompiler時,提到了Bytecode混淆以及bytecode優化,JRockit的態度是bytecode混淆時將name進行混淆是靠譜的,但若是對controlflow進行混淆,就不太好了,由於這有可能會致使jitcompile時的有些優化也作不了了,而bytecode優化,JRockit的態度是應該避免,由於沒什麼太大的意義,更主要的優化仍是得靠jitcompiler。server
JRockit的JITCompiler的實現和Hotspot另一個很大的不一樣在於JRockit並未採用on-stackreplacement,據JRockit的研究,這個沒有太大必要,固然,對於編寫benchmark代碼時則要注意這個不一樣。
JITCompiler在compile時還須要考慮的幾個重點問題:
一、爲GC提供必要的信息;
二、爲查錯提供必要的信息,例如代碼的行數、變量名等;
從這章的內容能夠看到,JRockit爲了可以讓Java代碼可以高效的執行,是作出了很是多的努力的,也能夠看到不少JRockit與Hotspot不一樣的地方,甚至能夠看出Java代碼的執行比C代碼的執行高效都是有可能的,:)。