使用hsdis與jitwatch查看JIT后的匯編碼

一、摘要

?之前在《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/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容