即時(JIT)編譯器是Java?運行時環(huán)境的組件,可提高運行時Java應(yīng)用程序的性能。
Java程序由類組成,這些類包含與平臺無關(guān)的字節(jié)碼,可以由JVM在許多不同的計算機(jī)體系結(jié)構(gòu)上解釋。在運行時,JVM加載類文件,確定每個單個字節(jié)碼的語義,并執(zhí)行適當(dāng)?shù)挠嬎恪=忉屵^程中額外的處理器和內(nèi)存使用情況意味著Java應(yīng)用程序比本地應(yīng)用程序執(zhí)行得更慢。JIT編譯器通過在運行時將字節(jié)碼編譯為本機(jī)機(jī)器代碼來幫助提高Java程序的性能。
JIT編譯器默認(rèn)情況下處于啟用狀態(tài),并在調(diào)用Java方法時被激活。JIT編譯器將該方法的字節(jié)碼編譯為本地機(jī)器代碼,“及時”編譯以運行。編譯方法后,JVM會直接調(diào)用該方法的已編譯代碼,而不是對其進(jìn)行解釋。從理論上講,如果編譯不需要處理器時間和內(nèi)存使用量,則編譯每種方法都可以使Java程序的速度接近本機(jī)應(yīng)用程序的速度。
JIT編譯確實需要處理器時間和內(nèi)存使用率。JVM首次啟動時,將調(diào)用數(shù)千種方法。即使程序最終達(dá)到了非常好的峰值性能,編譯所有這些方法也會嚴(yán)重影響啟動時間。
在實踐中,方法不是在第一次調(diào)用時編譯的。對于每種方法,JVM維護(hù)一個調(diào)用計數(shù),每次調(diào)用該方法時,該計數(shù)都會增加。JVM解釋一個方法,直到其調(diào)用計數(shù)超過JIT編譯閾值為止。因此,經(jīng)常使用的方法在JVM啟動后立即進(jìn)行編譯,而較少使用的方法則在以后編譯,或者根本不編譯。JIT編譯閾值可幫助JVM快速啟動,并仍具有改進(jìn)的性能。精心選擇了閾值,以在啟動時間和長期性能之間獲得最佳平衡。
編譯方法后,其調(diào)用計數(shù)將重置為零,并且對該方法的后續(xù)調(diào)用將繼續(xù)增加其計數(shù)。當(dāng)方法的調(diào)用計數(shù)達(dá)到JIT重新編譯閾值時,JIT編譯器將對其進(jìn)行第二次編譯,并使用比上一次編譯更大的優(yōu)化選擇。重復(fù)此過程,直到達(dá)到最大優(yōu)化級別。Java程序最繁忙的方法總是最積極地進(jìn)行優(yōu)化,從而最大程度地提高了使用JIT編譯器的性能。JIT編譯器還可以在運行時測量操作數(shù)據(jù),并使用該數(shù)據(jù)來提高進(jìn)一步重新編譯的質(zhì)量。
可以禁用JIT編譯器,在這種情況下,將解釋整個Java程序。除了診斷或解決JIT編譯問題外,不建議禁用JIT編譯器。
參考:
1.https://www.ibm.com/support/knowledgecenter/SSYKE2_7.1.0/com.ibm.java.aix.71.doc/diag/understanding/jit_overview.html
2.https://stackoverflow.com/questions/95635/what-does-a-just-in-time-jit-compiler-do