JIT 是 just in time 的縮寫, 也就是即時編譯編譯器。web
在運行時 JIT 會把翻譯過的機器碼保存起來,以備下次使用,所以從理論上來講,採用該 JIT 技術能夠接近之前純編譯技術。下面咱們看看,JIT 的工做過程。緩存
備註:寄存器的使用是編譯器的一個很是廣泛的優化。寄存器的速度比主存快不少。服務器
從優化的角度講,最簡單的選擇就是使用 server 編譯器的分層編譯技術,這將解決大約 90%左右的與編譯器直接相關的性能問題。最後,請保證代碼緩存的大小設置的足夠大,這樣編譯器將會提供最高的編譯性能。性能
HotSpot中有編譯器和解釋器並存。優化
HotSpot中內置兩個JIT編譯器:線程
JVM根據自身版本和機器硬件性能自動選擇翻譯
解釋器和編譯器搭配使用成爲混合模式(Mixed Mode)server
分層編譯:根據比那一塊兒編譯,優化的規模耗時,劃分出不一樣的編譯層次對象
分層編譯後,Client Compiler和Server Compiler將會同時工做,代碼可能會被屢次編譯,用Client得到更高的編譯速度,用Server得到更好的編譯質量,解釋執行的時候無需蒐集性能監控信息blog
熱點代碼有兩類:
判斷熱點的方法主要有兩種:
基於採樣的熱點探測(Sample Based Hot Spot Detection):週期性檢查各個線程的棧頂,發現某個(某些)方法常常出如今棧頂,就是熱點方法
有點簡單高效,能夠獲取方法調用關係(將調用堆棧展開便可)
缺點是很難精確確認方法熱度,容易受到線程阻塞等外界因素影響
基於計數器的熱點探測(Counter Based Hot Spot Detection):爲每一個方法(甚至代碼塊)創建計數器,統計方法調用次數,若是執行超過閾值就認爲是熱點方法。缺點是實現較爲困難。優勢是結果更精確。
基於計數器的探測:
Client模式下默認1500次,Server下默認10000次,根據參數-XX:CompileThreshold設定。
調用一個方法,先檢查是否存在JIT編譯版本本地代碼,存在優先使用本地代碼,不存在將計數器加1。而後判斷調用計數器和回邊計數器之和是否大於閾值,若是超過,用JIT編譯器提交編譯請求。JIT編譯完成後方法調用入口就被系統換成新的。下次調用已編譯版本。
計數器熱度衰減(Counter Decay超過必定的時間限度,方法的調用次數仍未達到閾值,方法計數器減小一半。在垃圾收集期間執行,用-UseCounterDecay來關閉,以統計絕對次數。用-XX:CounterHalfLifeTime設置半半衰週期。
回邊計數器:統計方法中方法體代碼執行的次數,在字節碼中遇到控制流向後跳動的指令成爲回邊(Back Edge)。
回邊計數器閾值能夠用-XX:OnStackReplacePercentage來間接調整。
回邊計數器沒有熱度衰減過程。
JVM默認狀況下對於即時編譯請求在編譯完成以前,都按照解釋方式執行,編譯動做在後臺線程執行
參數-XX:-BackgroundCompilation禁止後臺編譯,此時編譯請求會等待,直到編譯完成後直接執行本地代碼
本文由猿必過 YBG 發佈