一映九、摘要
?之前在《Java class文件結(jié)構(gòu)(實(shí)例篇)》這一篇文章中講解了我們通過javap
命令查看編譯成class的字節(jié)碼文件,字節(jié)碼是JVM執(zhí)行需要使用到的文件暖呕,但是cpu執(zhí)行的應(yīng)該是匯編指令呈枉;那么,我們應(yīng)該如何來看JIT之后的匯編碼呢剩蟀?如果我們能夠通過工具來閱讀匯編指令,這個(gè)將有利于我們從操作系統(tǒng)或者更底層的角度來分析我們的Java程序切威。本文將從hsdis和jitwatch兩個(gè)工具的角度來分析育特,怎么樣閱讀JIT之后的匯編碼。
二先朦、使用hsdis生成程序執(zhí)行生成的jit匯編碼日志
?這里將不講述hsdis怎么安裝缰冤,大家自行g(shù)oogle或者百度下犬缨;我是直接將hsdis-amd64.dll
文件放到我的jdk1.8.0_144\jre\bin\server
路徑下,如圖:
?接下來給一個(gè)小段的程序?yàn)槔嫘常瑏砩稍摮绦虻腏IT之后的匯編碼日志文件:
/**
* <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í)行時(shí)JVM參數(shù)遍尺,也即打印匯編碼的日志文件
-server -XX:+UnlockDiagnosticVMOptions -XX:+TraceClassLoading -XX:+PrintAssembly -XX:+LogCompilation -XX:LogFile=live.log
?執(zhí)行SimpleInliningTest這個(gè)類之后,變會(huì)在工程的根目錄生成live.log文件涮拗,同時(shí)控制臺(tái)也會(huì)打印匯編碼指令:
三乾戏、使用jitwatch查看hsdis生成的匯編碼日志
?從https://github.com/AdoptOpenJDK/jitwatch下載完整的jitwatch源碼包,然后使用maven命令進(jìn)行編譯三热,由于編譯test文件會(huì)報(bào)錯(cuò)鼓择,所以maven編譯的時(shí)候忽略test包的編譯,使用如下命令:
mvn clean install -Dmaven.test.skip=true
?編譯成功之后就漾,直接使用launchUI.bat命令打開jitwatch工具:
?Open log打開第二章中生成的live.log呐能,并通過config來配置代碼的源碼路徑和class的路徑:
?點(diǎn)擊start開始執(zhí)行:
?執(zhí)行完成之后,單擊右邊的方法或者點(diǎn)擊TriView:
?我們能看到TriView視圖:左邊為Java源代碼抑堡,中間為字節(jié)碼摆出,右邊為生成的匯編碼;
?當(dāng)再單擊Inlined Into按鈕后首妖,我們將看到內(nèi)聯(lián)的所有方法:
?當(dāng)單擊Chain之后偎漫,我們將看到已編譯和內(nèi)聯(lián)子項(xiàng)鏈:
?jitwatch工具也同樣給我們查看一些熱或者不熱的,而且不能內(nèi)聯(lián)的一些大型方法的建議:
?我們還可以按字節(jié)代碼大小和native代碼大小查看最大的方法:
?我們也能看到有多少個(gè)方法被編譯了有缆,有多少被C1編譯了象踊,有多少被C2編譯了:
?這是編譯的方法的時(shí)間線圖。我們可以點(diǎn)擊與每種方法相對(duì)應(yīng)的彩色線條棚壁。
?最后是最重要的標(biāo)簽杯矩。在這里,您可以查看代碼消耗了多少緩存袖外。您可以根據(jù)此用法更改代碼緩存內(nèi)存大小史隆。
?我們也可以直接將代碼貼到j(luò)itwatch里面的sandbox中進(jìn)行執(zhí)行操作:
四、通過Idea查看class對(duì)應(yīng)的匯編碼
?在把hsdis-amd64.dll
放到JDK的server下面之后在刺,在idea運(yùn)行類上面配置如下信息逆害,執(zhí)行class文件即可打印匯編指令
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
參考:
https://github.com/AdoptOpenJDK/jitwatch/wiki
http://marjavamitjava.com/jitwatch-use-analyze-jit-compilation/