一、JVM調優介紹之JTI編譯器
JTI編譯器(just in time)
開發語言可以以編譯方式來划定為編譯型語言,解釋型語言,分層編譯型語言(包含解析和編譯共存)
先來了解下計算機如何讀取代碼程序,由於計算機的CPU只能執行相對少而特定的命令,而這種命令的形式就是匯編碼或者二進制碼。因此CPU所執行的程序都要翻譯成這種指令,CPU才可以識別 並且運行。
不同產商的CPU對應可以識別的指令集也不太一樣,但是新版本的CPU通常是能夠兼容老版本CPU的指令集的,但是反過來,老版本的CPU是沒辦法兼容新版本的CPU指令集的。
而編譯型語言就是利用編譯器靜態產生相對應CPU能識別的二進制文件,如果有什么機器能帶有CPU的指令集的話 也可以識別這些編譯后的二進制文件。也就是能運營對應的程序了。
至於還有一種解釋型語言,這些語言的讀取不需要依賴CPU去讀取特定的二進制文件,而是依賴語言對應的解釋器,當程序運行時,解釋器會將對應的代碼轉換成特定的二進制碼。
它與編譯型語言的區別在於:編譯型語言是預編譯,即程序在啟動之前就把代碼轉換成CPU能識別的二進制文件了。但是解釋型語言是在程序運行的時候通過解釋器將代碼逐一轉換成二進制語言供CPU讀取。
這樣2種機制就產生了對應的優缺點:編譯型語言因為在程序啟動之初就將代碼轉換成了二進制文件,所以運行程序相對較快。缺點也很明顯,可移植性比較差,如果CPU無法識別對應的二進制指令就無法運行程序。
相比於編譯型的程序,解釋型程序依賴解釋器啟動,所以凡是裝有解釋器的計算機都可以運行對應的程序,因為由解釋器將代碼轉換為CPU可識別的二進制文件,但是由於是運行后邊運行邊轉換 所以程序的運行速度肯定就沒有編譯型程序那么快。
舉個例子:一個循環代碼,編譯型只需要編譯一次就可以一直執行這段代碼,但是解釋型語言就需要在每次循環體中反復的去解析代碼,將它轉換成二進制碼。
編譯型語言:如C++,Fortran。 解釋型語言:如PHP,Perl。
而JAVA則是二者的結合,JAVA應用會被編譯,但是不是編譯成CPU的二進制碼,而是編譯成JAVA平台自己可以識別的二進制碼,而這個編譯是在程序執行是進行的,所以java的編譯也稱為"即時編譯(JIT)"
(1).JIT之熱點編譯
上述說到java由於是在程序執行時編譯,所以java虛擬機的核心編譯器是即時編譯器。
熱點編譯(HotSpot):HotSpot來自於它看待代碼編譯的方式,當一個程序只有一部分代碼經常被執行,並且程序的性能取決於執行的這些代碼有對快。那么這些代碼就被稱為該程序的熱點。
JVM在執行代碼時其實並不會去編譯代碼。
原因:
(1)如果執行的代碼只是執行一次,那么解釋該代碼的速度就會比編譯后再執行的速度更快。
(2)是為了優化代碼,如果JVM執行的特定的代碼次數越多,虛擬機就會越了解這段代碼,這使得JVM在編譯代碼時可以做出對這段特定代碼的優化。舉個例子:b = obj1.equals(obj2),這段代碼在一開始執行時為了需要知道obj1是什么類型,在執行equals方法之前會去找obj1的類型,然后再執行equals方法,但是隨着這段代碼的執行次數增加,JVM知道了obj1就是String類型,那么在編譯后就會變成b=String.equals(obj2),減少了一次類型確認的步驟。
(2).選擇編譯器類型(client,server,分層編譯(即同時使用))
client與server兩種編譯器的區別在於:編譯代碼的時機不同,client開啟編譯要早於server。也就意味着,在代碼執行的開始階段,client比server要快,因為它的編譯代碼相比於server而言要多。它們2者的選擇根據需求而定,如果比較在意啟動時的時間,那么一般會選擇client。但目前大都數都是使用分層編譯,它的啟動性能非常的接近client,又能包含后期得代碼熱點優化。而且在JDK1.8后JVM默認的編譯類型就是分層編譯。