一、摘要
?之前在《Java class文件結(jié)構(gòu)(實例篇)》這一篇文章中講解了我們通過javap命令查看編譯成class的字節(jié)碼文件,字節(jié)碼是JVM執(zhí)行需要使用到的文件,但是cpu執(zhí)行的應該是匯編指令;那么,我們應該如何來看JIT之后的匯編碼呢?如果我們能夠通過工具來閱讀匯編指令,這個將有利于我們從操作系統(tǒng)或者更底層的角度來分析我們的Java程序。本文將從hsdis和jitwatch兩個工具的角度來分析,怎么樣閱讀JIT之后的匯編碼。
二、使用hsdis生成程序執(zhí)行生成的jit匯編碼日志
?這里將不講述hsdis怎么安裝,大家自行google或者百度下;我是直接將hsdis-amd64.dll文件放到我的jdk1.8.0_144\jre\bin\server路徑下,如圖:

?接下來給一個小段的程序為例,來生成該程序的JIT之后的匯編碼日志文件:
/**
* <Description> JVM參數(shù): -server -XX:+UnlockDiagnosticVMOptions -XX:+TraceClassLoading -XX:+PrintAssembly -XX:+LogCompilation -XX:LogFile=live.log<br>
*
* @author Sunny<br>
* @version 1.0<br>
* @taskId: <br>
* @createDate 2019/01/21 15:37 <br>
* @see com.sunny.concurrent.hsdis <br>
*/
public class SimpleInliningTest {
private int count = 0;
public static void main(String[] args) throws Exception {
SimpleInliningTest t = new SimpleInliningTest();
int sum = 0;
for (int i = 0; i < 1000000; i++) {
sum += t.m();
}
System.out.println(sum);
}
public int m() {
int i = count;
i = m2(i);
i += count;
i *= count;
i++;
return i;
}
public int m2(int i) {
if (i % 10 == 0) {
i += 1;
} else if (i % 10 == 1) {
i += 2;
} else if (i % 10 == 2) {
i += 3;
}
return i;
}
}
?配置執(zhí)行時JVM參數(shù),也即打印匯編碼的日志文件
-server -XX:+UnlockDiagnosticVMOptions -XX:+TraceClassLoading -XX:+PrintAssembly -XX:+LogCompilation -XX:LogFile=live.log

?執(zhí)行SimpleInliningTest這個類之后,變會在工程的根目錄生成live.log文件,同時控制臺也會打印匯編碼指令:

三、使用jitwatch查看hsdis生成的匯編碼日志
?從https://github.com/AdoptOpenJDK/jitwatch下載完整的jitwatch源碼包,然后使用maven命令進行編譯,由于編譯test文件會報錯,所以maven編譯的時候忽略test包的編譯,使用如下命令:
mvn clean install -Dmaven.test.skip=true

?編譯成功之后,直接使用launchUI.bat命令打開jitwatch工具:

?Open log打開第二章中生成的live.log,并通過config來配置代碼的源碼路徑和class的路徑:

?點擊start開始執(zhí)行:

?執(zhí)行完成之后,單擊右邊的方法或者點擊TriView:


?我們能看到TriView視圖:左邊為Java源代碼,中間為字節(jié)碼,右邊為生成的匯編碼;

?當再單擊Inlined Into按鈕后,我們將看到內(nèi)聯(lián)的所有方法:


?當單擊Chain之后,我們將看到已編譯和內(nèi)聯(lián)子項鏈:

?jitwatch工具也同樣給我們查看一些熱或者不熱的,而且不能內(nèi)聯(lián)的一些大型方法的建議:


?我們還可以按字節(jié)代碼大小和native代碼大小查看最大的方法:


?我們也能看到有多少個方法被編譯了,有多少被C1編譯了,有多少被C2編譯了:


?這是編譯的方法的時間線圖。我們可以點擊與每種方法相對應的彩色線條。

?最后是最重要的標簽。在這里,您可以查看代碼消耗了多少緩存。您可以根據(jù)此用法更改代碼緩存內(nèi)存大小。


?我們也可以直接將代碼貼到jitwatch里面的sandbox中進行執(zhí)行操作:


四、通過Idea查看class對應的匯編碼
?在把hsdis-amd64.dll放到JDK的server下面之后,在idea運行類上面配置如下信息,執(zhí)行class文件即可打印匯編指令
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly


參考:
https://github.com/AdoptOpenJDK/jitwatch/wiki
http://marjavamitjava.com/jitwatch-use-analyze-jit-compilation/