java虛拟機熱點代碼檢測什麼鬼?
-----------------來自小馬哥的故事
1. HotSpot曆史
SUN的JDK版本從1.3.1開始運用HotSpot虛拟機, 2006年底開源,主要使用C++實作,JNI接口部分用C實作。
HotSpot是較新的Java虛拟機,用來代替JIT(Just in Time),可以大大提高Java運作的性能。
Java原先是把源代碼編譯為位元組碼在虛拟機執行,這樣執行速度較慢。而HotSpot将常用的部分代碼編譯為本地(原生,native)代碼,這樣顯着提高了性能。 HotSpot JVM 參數可以分為規則參數(standard options)和非規則參數(non-standard options)。
規則參數相對穩定,在JDK未來的版本裡不會有太大的改動。 非規則參數則有因更新JDK而改動的可能。 規則和非規則參數這裡不做介紹了,網上資料很多。
2.HotSpot基礎知識
HotSpot包括一個解釋器和兩個編譯器(client 和 server,二選一的),解釋與編譯混合執行模式,預設啟動解釋執行。
編譯器:java源代碼被編譯器編譯成class檔案(位元組碼),java位元組碼在運作時可以被動态編譯(JIT)成本地代碼(前提是解釋與編譯混合執行模式且虛拟機不是剛啟動時)。
解釋器: 解釋器用來解釋class檔案(位元組碼),java是解釋語言(書上這麼說的)。
- server啟動慢,占用記憶體多,執行效率高,适用于伺服器端應用; client啟動快,占用記憶體小,執行效率沒有server快,預設情況下不進行動态編譯,适用于桌面應用程式。
- 由-XX:+RewriteFrequentPairs參數控制 client模式預設關閉,server模式預設開啟
- 在jre安裝目錄下的lib/i386/jvm.cfg 檔案下。
java -version
Java HotSpot(TM) Client VM (build 14.3-b01, mixed mode, sharing)
複制
mixed mode 解釋與編譯 混合的執行模式 預設使用這種模式
java -Xint -version
Java HotSpot(TM) Client VM (build 14.3-b01, interpreted mode, sharing)
複制
interpreted 純解釋模式 禁用JIT編譯
java -Xcomp -version
Java HotSpot(TM) Client VM (build 14.3-b01, compiled mode, sharing)
複制
compiled 純編譯模式(如果方法無法編譯,則回退到解釋模式執行無法編譯的方法)
3.動态編譯
動态編譯(compile during run-time),英文稱Dynamic compilation;Just In Time也是這個意思。
HotSpot對bytecode的編譯不是在程式運作前編譯的,而是在程式運作過程中編譯的。
HotSpot裡運作着一個螢幕(Profile Monitor),用來監視程式的運作狀況。 java位元組碼(class檔案)是以解釋的方式被加載到虛拟機中(預設啟動時解釋執行)。 程式運作過程中,那一部分運用頻率大,那些對程式的性能影響重要。對程式運作效率影響大的代碼,稱為熱點(hotspot),HotSpot會把這些熱點動态地編譯成機器碼(native code),同時對機器碼進行優化,進而提高運作效率。對那些較少運作的代碼,HotSpot就不會把他們編譯。
HotSpot對位元組碼有三層處理:不編譯(位元組碼加載到虛拟機中時的狀态。也就是當虛拟機執行的時候再編譯),編譯(把位元組碼編譯成本地代碼。虛拟機執行的時候已經編譯好了,不要再編譯了),編譯并優化(不但把位元組碼編譯成本地代碼,而且還進行了優化)。
至于那些程式那些不編譯,那些編譯,那些優化,則是由螢幕(Profile Monitor)決定。
4.為什麼不靜态編譯那?
為什麼位元組碼在裝載到虛拟機之前就編譯成本地代碼那?
動态編譯器也在許多方面比靜态編譯器優越。靜态編譯器通常很難準确預知程式運作過程中究竟什麼部分最需要優化。
函數調用都是很浪費系統時間的,因為有許多進棧出棧操作。是以有一種優化辦法,就是把原來的函數調用,通過編譯器的編譯,改成非函數調用,把函數代碼直接嵌到調用出,變成順序執行。
面向對象的語言支援多态,靜态編譯無效确定程式調用哪個方法,因為多态是在程式運作中确定調用哪個方法。
本文由 小馬哥 創作,采用 知識共享署名4.0 國際許可協定進行許可
本站文章除注明轉載/出處外,均為本站原創或翻譯,轉載前請務必署名