Java 虚拟机(JVM)作为一种现代化的虚拟机,具备即时编译(Just-In-Time, JIT)功能,可以将热点代码编译为高效的本地机器码以提高性能。在实际开发和性能调优中,我们可能需要分析 JVM 将 Java 字节码编译成的汇编指令。本篇博客将详细介绍如何使用 HSDIS 和 JitWatch 工具来查看和分析这些生成的汇编代码。


一、HSDIS 简介

HSDIS(HotSpot Disassembler)是 HotSpot JVM 的反汇编插件,可以将 JIT 编译器生成的机器码转换成人类可读的汇编指令。HSDIS 是 JDK 的非官方组件,因此需要手动下载或编译。

二、JITWatch 简介

JITWatch 是一个用于分析 JVM JIT 编译过程的可视化工具。它可以解析 JVM 日志文件(通常是通过 -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation 生成的),并展示 JIT 编译的详细信息,包括内联决策和汇编代码。

三、环境准备

以下步骤基于 Linux 环境,但可以适配其他操作系统。

  1. 安装 JDK

    确保你的系统安装了支持 HSDIS 和 JIT 日志的 JDK(推荐使用 OpenJDK 或 Oracle JDK 8/11,本文使用的是Oracle JDK 8)。

  2. 下载或编译 HSDIS

  • 将生成的 hsdis-<arch>.so 放到 JDK 的 $JAVA_HOME/jre/bin/server 目录下。
  1. 安装 JITWatch

生成汇编代码

1. 编写测试代码

首先,创建一个简单的 Java 类用于测试:

1
2
3
4
5
6
7
8
9
10
11
public class Test {
public static void main(String[] args) {
for (int i = 0; i < 10_000_000; i++) {
compute(i);
}
}

private static int compute(int x) {
return (x * 2 + 1) / 3;
}
}

2. 使用 HSDIS 查看汇编

运行上述代码时,启动 JVM 时添加 HSDIS 配置参数:

1
2
3
4
5
-XX:+UnlockDiagnosticVMOptions
-XX:+PrintAssembly
-Xcomp
-XX:+LogCompilation
-XX:LogFile=/home/yao/hotspot.log

其中:

  • -XX:+PrintAssembly:启用汇编代码打印。
  • -XX:+LogCompilation:生成 JIT 日志文件。
  • -XX:LogFile:指定 JIT 日志文件的位置。

运行后,终端将输出大量信息,其中包含 compute 方法的汇编代码。你可以通过分析这些汇编指令了解 JVM 如何优化你的代码。

3. 使用 JitWatch 分析

  1. 配置源码目录和编译字节码目录


2.打开生成的 hotspot.log 文件。并启动分析


常见问题

  1. 未加载 HSDIS 动态库

    • 检查 HSDIS 文件名是否正确,并确认其路径与 JVM 的 lib 目录匹配。
    • 使用 java -version 确认使用的是预期的 JVM。
  2. 汇编输出乱码

    • 确保 JVM 使用的指令集架构与 HSDIS 编译版本一致(如 x86_64)。
    • 检查终端编码是否支持正确显示特殊字符。
  3. JitWatch 无法加载日志

    • 确保日志文件完整无误。
    • 使用 grep 检查日志是否包含方法编译记录。

总结

通过 HSDIS 和 JitWatch,我们可以深入了解 JVM 的 JIT 编译过程以及生成的汇编代码。对于性能调优或研究 JVM 工作原理,这些工具提供了强大的支持。希望本文能够帮助你快速上手这些工具,进一步探索 Java 性能优化的奥秘!