Skip to content

MacOS 环境下使用 hsdis 和 JIT Watch 查看汇编代码 #40

Description

@funnycoding

操作系统:macOS 10.14.6

JDK_Version:1.8.072

JITWatch_Version:jitwatch-1.3.0

1. 动机

学习并发时看到这么一句话,关于 volatile 关键字的:「编译器将在volatile字段的读写操作前后各插入一些内存屏障。」

于是我想去看看编译器是插入的内存屏障。

结果发现字节码中并没有在被 volatile 修饰的变量周围插入特殊的字节码。

后来经查询需要看的被 JIT 即时编译器编译过的汇编代码,这里就涉及到了对「汇编的反编译」。

2.准备工作

  1. 下载反汇编器:HotSpot Disassembler 其本质是一个动态链接库, MacOS使用的下载地址在这里 : https://github.com/liuzhengyang/hsdis/blob/master/build/macosx-amd64/hsdis-amd64.dylib
  2. 将下载好的 hsdis-amd64.dylib 放到 jdk/jre/lib 下 例如我的目录是:

/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre/lib

  1. 使用 java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -version 检测反汇编器是否 OK 如果输出中你能看到下图中的 PringtAssembly is enabled 就代表 OK 了

  1. 安装 JITWatch ,GithubRepoUrl:https://github.com/AdoptOpenJDK/jitwatch
  2. 编译/启动 JITWatch gradlew clean build run 因为 这个版本的 JITWATCH 是用 Gradle 来管理依赖,而我本人还是比较喜欢 Maven,因为每次使用Gradle 只要版本不同,就得下载一大堆 Gradle 的依赖,这次也不例外 如下图:

image-20200409223827600

下载好之后这个shadowJar就自动打开了,软件就长这样:

OK,现在反汇编编译器也有了,查看 JIT 编译后的代码也有了,下一步就是生成一个 JIT Log 文件,同时注意,JIT 优化热点代码的前提之一就是有一定的循环数量,我的代码是这样的: 是极客时间课程中的一个样例代码,我加了100000次循环

public class VolatileExample {
    volatile int x = 0;
    volatile boolean v = false;

    public void writer() {
        x += 1;
        v = true;
    }

    public void reader() {
        if (v == true) {
            System.out.println(x);
        }
    }



    public static void main(String[] args) {
        VolatileExample example = new VolatileExample();
        for (int i = 0; i < 100000; i++) {
            example.writer();
        }
    }
}
  1. 编译 VolatileExample.java 命令: javac VolatileExample.java
  2. 配置执行时 JVM 参数,打印汇编日志文件
java -server -XX:+UnlockDiagnosticVMOptions -XX:+TraceClassLoading  -XX:+PrintAssembly -XX:+LogCompilation -XX:LogFile=VolatileExample.log[即将生成的文件名]  VolatileExample[你的类名]

执行完毕后就得到了这么一个JIT Log文件

  1. 使用 「JIT Watch」 打开生成好的 JIT 日志文件
    1. 点击 OpenLog 打开刚才生成的JIT 文件
    2. 点击 Config 配置 源码 和 Class 文件的地址,由于我的 源码 和 字节码文件都在一起,所以我配置的都是一个地址
    3. 点击 Start 正常的话就可以看到左边 Packages 里面多出来了 你自己定义的类
    4. 点击你自己定义的类,跳入 TriView 视图

  1. 阅读 JIT Watcher 反编译出来的汇编代码

可以看到这里就是被 volatile 修饰的变量 底层汇编代码对这个关键字做的处理

从 Java 源码到字节码再到汇编代码,一路跟下来,确认了理论正确之后,长舒了一口气,眼见为实。 如果你也有类似的需求,希望这篇文章能帮助到你。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions