慢慢開始深刻了解java,才知道java虛擬機有不少種,其中最爲知名的應該就是hotspot了,接下來是hotspot的一點簡單介紹。java
沒錯,Java是解釋語言,但並不意味着它必定被解釋執行。早期
的虛擬機確實一條一條指令解釋執行,但人們發現這樣效率過低,
不知足各類要求,所以出現了許多其它虛擬機,如JIT的虛擬機。
HotSpot也是相似一種虛擬機,自從SUN買下後,已經把它放入
JRE 1.3以及後續版本中。
採用HotSpot的Java虛擬機,已經很難說Java是被虛擬機解釋執行了,
緣由是HotSpot其實是把Java的bytecode編譯成Native code,
而後運行。
實際上在HotSpot虛擬機中,有兩個技術是相當重要的,即動態編譯和
Profiling。HotSpot對bytecode的編譯,不是在程序運行前預先編譯的,
而是在程序運行過程當中,動態編譯(compile during run-time),英文稱
Dynamic compilation。其實Just In Time也就是這個意思。
HotSpot是如何動態編譯Javad的bytecode呢?它採用的是一種smart的辦法。
HotSpot裏有一個運行監視器,即Profile Monitor(不知國內如何翻譯Profile),
專門監視程序運行中,哪一部分運用頻度大, 哪些對性能影響相當重要。
固然Profile Monitor有一些算法,這些算法未必十全十美,但大致是能較好
得到相關信息的。對於那些對程序運行效率影響交大的代碼,稱爲熱點,
即hot spot,HotSpot會把這些部門動態地編譯成機器碼,Native code,
同時也對機器碼進行優化(相似C編譯器的一些優化),從而而提升運行效率。
而那些較少運行的Code,HotSpot虛擬機就再也不浪費時間把它們編譯。
整體來看,Java bytecode是以解釋方式被load到虛擬機的。但虛擬機的
分析器根據一段運行,獲知對程序效率影響最大的部分,而後經過動態
編譯,同時進行優化,編譯成機器碼,而後爲接下來的運行加速。總的
來講,HotSpot對bytecode有三層處理:不編譯,編譯,編譯並優化。
至於程序哪部分不編譯,哪部分編譯,哪部分作何種優化,則由Profile
Monitor決定。
那麼爲何Java採用動態編譯器而不是象C++這樣採用靜態編譯器呢?
虛擬機提供的跨平臺運行條件當然是一方面,動態編譯器也在許多方面
比靜態編譯器優越。Profiling就是一個例子。靜態編譯器一般很難準確
預知程序運行過程當中究竟什麼部分最須要優化。靜態編譯器雖然能夠把Java
所有編譯成Native Code,但卻作不到動態編譯器那樣的優化。
另外一個典型的例子,叫作Method inlining。咱們知道不管是在C仍是在
Java裏,函數調用都是很浪費系統時間的,由於有許多進棧出棧操做。
所以有一種優化辦法,就是把原來的函數調用,經過編譯器的編譯,改爲
非函數調用,把函數代碼直接嵌到調用出,變成順序執行。
但這一方法在Java/C++這樣的面向對象的語言的編譯器中,較難很好實現。
那些靜態編譯器,一般能夠把private,static等函數進行Method inlining,
但因爲這些面向對象的語言支持函數重載,支持動態聯編(不知道是否是這樣
翻譯,Overridden, dynamic binding),所以靜態編譯器並不知道究竟應該
把函數的哪一個實現給inline了。
HotSpot的動態編譯,因爲有對函數調用的監視,所以能夠準確地知道一些環境
下,那些被重載和動態識別的函數能夠如何被inline到調用者那裏去,所以
實際上對於一些Server應用來講,能夠大幅度提升效率。
HotSpot實際上有兩個版本,一個是Server版,一個是Client版。但它們的結構
和本質都是同樣的,只是有些地方優化不同。
瞭解了這些,就知道,有時候Java的程序甚至能比C程序運行還快。算法