HSDIS java汇编工具分析 JVM 代码执行

HSDIS,一个Sun官方推荐的HotSpot虚拟机JIT编译代码的反汇编插件。

windows 电脑上, 在 hsdis HotSpot Disassembly Plugin Downloads (chriswhocodes.com) 下载 hsdis-amd64.dll 安装到 %JAVA_HOME\jre\bin\server 目录下

image-20221017155717734

验证是否安装成功

java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -version

通过 JITwatch 的 release 知道,如果未检测到 hsdis,则 JITWatch 沙盒将提供从 https://chriswhocodes.com/hsdis/ 下载hsdis-amd64.dll

测试代码

package com.person;
 
public class VolatileVisibilityTest {
    private static volatile boolean initFlag = false;
 
    public static void main(String[] args) throws InterruptedException {
        new Thread(()->{
            System.out.println("waiting data.....");
            while (!initFlag){
 
            }
            System.out.println("=========success.");
        }).start();
 
        Thread.sleep(2000);
 
        new Thread(()->prepareData()).start();
 
    }
 
    public static void prepareData(){
        System.out.println("prepare data end.");
        initFlag = true;
    }
}

没配置VM optons参数,控制台输出程序结果

waiting data.....
prepare data end.
=========success.

配置VM optons参数, IDEA 找到Edit Configurations,点击 Modify options 找到 Add VM options 或者使用快捷键Alt + F

VM optons 详细参数可以查看.java 工具参考_vm参数java (oracle.com)

-server
-XX:+UnlockDiagnosticVMOptions
-XX:+PrintAssembly
-XX:+LogCompilation
-XX:LogFile=D:\Java\IdeaProjects\test\data\log\%t-hotspot.log

只需要编译 *VolatileTest.increase*VolatileTest.decrease 这两个方法,并且将日志输出到 /var/log/hotspot.log 文件中,VM options 参数是这样子的

-XX:+UnlockDiagnosticVMOptions 
-XX:+PrintAssembly 
-Xcomp 
-XX:CompileCommand=compileonly,*VolatileTest.increase
-XX:CompileCommand=compileonly,*VolatileTest.decrease 
-XX:+LogCompilation 
-XX:LogFile=/var/log/hotspot.log

注意:data\log 目录必须先配置好

配置VM optons参数,控制台输出程序结果,可以看到汇编语言

4bae3f9a8: mov     rsi,rdx
  0x00000154bae3f9ab: mov     rdi,154d39aab18h  ;   {metadata(method data for {method} {0x00000154d3888920} 'next' '()Ljava/lang/Object;' in 'java/util/Collections$UnmodifiableCollection$1')}
  0x00000154bae3f9b5: mov     esi,dword ptr [rsi+8h]
  0x00000154bae3f9b8: shl     rsi,3h
  0x00000154bae3f9bc: cmp     rsi,qword ptr [rdi+110h]
  0x00000154bae3f9c3: jne     154bae3f9d2h
  0x00000154bae3f9c5: add     qword ptr [rdi+118h],1h
  0x00000154bae3f9cd: jmp     154bae3fa38h
  0x00000154bae3f9d2: cmp     rsi,qword ptr [rdi+120h]
  0x00000154bae3f9d9: jne     154bae3f9e8h
  0x00000154bae3f9db: add     qword ptr [rdi+128h],1h
  0x00000154bae3f9e3: jmp     154bae3fa38h
  0x00000154bae3f9e8: cmp     qword ptr [rdi+110h],0h
  0x00000154bae3f9f3: jne     154bae3fa0ch
  0x00000154bae3f9f5: mov     qword ptr [rdi+110h],rsi
  
  ......省略大量代码
  
  [Exception Handler]
[Stub Code]
  0x00000154bae73720: call    154bad548e0h      ;   {no_reloc}
  0x00000154bae73725: mov     qword ptr [rsp+0ffffffffffffffd8h],rsp
  0x00000154bae7372a: sub     rsp,80h
  0x00000154bae73731: mov     qword ptr [rsp+78h],rax
  0x00000154bae73736: mov     qword ptr [rsp+70h],rcx
  0x00000154bae7373b: mov     qword ptr [rsp+68h],rdx
  0x00000154bae73740: mov     qword ptr [rsp+60h],rbx
  0x00000154bae73745: mov     qword ptr [rsp+50h],rbp
  0x00000154bae7374a: mov     qword ptr [rsp+48h],rsi
  0x00000154bae7374f: mov     qword ptr [rsp+40h],rdi
  0x00000154bae73754: mov     qword ptr [rsp+38h],r8
  0x00000154bae73759: mov     qword ptr [rsp+30h],r9
  0x00000154bae7375e: mov     qword ptr [rsp+28h],r10
  0x00000154bae73763: mov     qword ptr [rsp+20h],r11
  0x00000154bae73768: mov     qword ptr [rsp+18h],r12
  0x00000154bae7376d: mov     qword ptr [rsp+10h],r13
  0x00000154bae73772: mov     qword ptr [rsp+8h],r14
  0x00000154bae73777: mov     qword ptr [rsp],r15
  0x00000154bae7377b: mov     rcx,7794f910h     ;   {external_word}
  0x00000154bae73785: mov     rdx,154bae73725h  ;   {internal_word}
  0x00000154bae7378f: mov     r8,rsp
  0x00000154bae73792: and     rsp,0fffffffffffffff0h
  0x00000154bae73796: mov     r10,7762e3e0h     ;   {runtime_call}
  0x00000154bae737a0: call indirect r10
  0x00000154bae737a3: hlt
[Deopt Handler Code]
  0x00000154bae737a4: mov     r10,154bae737a4h  ;   {section_word}
  0x00000154bae737ae: push    r10
  0x00000154bae737b0: jmp     154bad27600h      ;   {runtime_call}
  0x00000154bae737b5: hlt
  0x00000154bae737b6: hlt

通过命令行查看 java 汇编

javac Test.java
-server -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:+LogCompilation
-XX:LogFile=D:\Java\IdeaProjects\test\data\log\%t-hotspot.log

JITWatch(Just In Time compilers)

JITWatch的 GitHub 的地址https://github.com/AdoptOpenJDK/jitwatch

JITWatch 是 HotSpot JIT 编译器的日志分析器和可视化程序

JITWatch wiki地址

描述:

用于了解 Java 热点实时 (JIT) 编译器在程序执行期间的行为的工具。

通过处理热点.log JVM 输出文件来工作。

该工具最初是作为一种学习工具,以更好地了解热点和JavaFX。

我希望你觉得它有用:)


为什么我要使用 JIT 监视?

  • 验证您认为对性能至关重要的方法是否在程序执行期间进行了 JIT 编译。
  • 要了解在执行中的哪个阶段编译了性能关键型方法。
  • 了解调整 JVM 编译阈值的效果。
  • 为了更好地了解热点 JIT 编译器。
  • 查看源代码如何转换为字节码和程序集。

特征

  • 浏览类树并查看哪些方法已进行 JIT 编译、JIT 编译发生的时间以及有关编译的信息。
  • 装载源代码、jar 和类树以跳转到方法的源代码、字节码和程序集。
  • 绘制随时间变化的 JIT 编译,并可视化方法的 JIT 编译时间。
  • 查看最大本机方法、字节码最多的方法、最长编译时间等的顶级列表。
  • 在简化的BSD许可证下开源。

通过命令,启动JITWatch程序

 java -jar jitwatch-ui-1.4.7-shaded-win.jar

image-20221013193654596

在 jitwatch 中配置 idea 中的测试程序

  1. 页面选择 config ,配置要调试的项目 src 源码路径,和 class 编译路径

    image-20221013201111762

  2. 打开 hotspot.log

    image-20221013201152570

  3. 点击 start ,选中指定的类,再选择右侧的具体方法,则弹出jit编译结果

    image-20221013221720270

    展示java 源码 字节码 汇编语言

    image-20221013201223836

参考资料:

(330条消息) openjdk12 hsdis windows构建_窗外蓝天的博客-CSDN博客_hsdis-amd

java汇编指令查看工具jitwatch - 掘金 (juejin.cn)

Building hsdis for OpenJDK 15 - Gunnar Morling

Developers disassemble! Use Java and hsdis to see it all. (oracle.com)

(330条消息) Java反汇编工具hsdis-jitwatch使用_At小明同学的博客-CSDN博客_java 反汇编工具

(330条消息) windows环境下使用jitwatch查看字节码以及汇编指令_d303577562的博客-CSDN博客

JIT的Profile神器JITWatch - 知乎 (zhihu.com)

How to build hsdis-amd64.dll and hsdis-i386.dll on Windows (dropzone.nfshost.com)

posted @ 2022-10-17 17:17  chengpopeye  阅读(498)  评论(0编辑  收藏  举报