深入理解可视化JVM 故障处理工具

本文内容过于硬核,建议有 Java 相关经验人士阅读。

1. 可视化工具

在 JDK 中为我们提供了大量的 JVM 故障处理工具,都在 JDK 的 bin 目录下:

深入理解可视化JVM 故障处理工具

这其中除了大量的命令行工具以外,还为我们提供了更加方便快捷的可视化工具,主要是以下这 4 个:

  • JConsole: 最古老的工具,早在 JDK 5 时期就已经存在的虚拟机监控工具。
  • JHSDB: 名义上在 JDK 9 中才正式提供,但之前已经以 sa-jdi.jar 包里面的 HSDB(可视化工具) 和 CLHSDB(命令行工具) 的形式存在了很长一段时间。
  • VisualVM: 在 JDK 6 Update 7 中首次发布,直到 JRockit Mission Control 与 OracleJDK 的融合工作完成之前,它都曾是 Oracle 主力推动的多合一故障处理工具,现在它已经从 OracleJDK 中分离出来,成为一个独立发展的开源项目。
  • JMC: Java Mission Control ,曾经是大名鼎鼎的来自 BEA 公司的图形化诊断工具,随着 BEA 公司被 Oracle 收购,它便被融合进 OracleJDK 之中。在 JDK 7 Update 40 时开始随 JDK 一起发布,后来 Java SE Advanced 产品线建立, Oracle 明确区分了 Oracle OpenJDK 和 OracleJDK 的差别, JMC 从 JDK 11 开始又被移除出 JDK 。

2. HSDB

HSDB(Hotspot Debugger) 是 JDK 自带的工具,用于查看 JVM 运行时的状态。

使用方式由于在 JDK 9 之前没有正式提供,所以也未在 JDK 的 bin 目录下提供直接可执行文件,需要在命令行执行命令才能启动。

首先在命令行中先 cd 至 C:\Program Files\Java\jdk1.8.0_221\lib 目录,然后执行:

java -cp .\sa-jdi.jar sun.jvm.hotspot.HSDB

我在执行这句命令的时候报了个错:

Exception in thread "Thread-1" java.lang.UnsatisfiedLinkError: Can't load library: C:\Program Files\Java\jdk-11.0.4\bin\sawindbg.dll
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2620)
at java.base/java.lang.Runtime.load0(Runtime.java:767)
at java.base/java.lang.System.load(System.java:1831)
at sun.jvm.hotspot.debugger.windbg.WindbgDebuggerLocal.<clinit>(WindbgDebuggerLocal.java:661)
at sun.jvm.hotspot.HotSpotAgent.setupDebuggerWin32(HotSpotAgent.java:567)
at sun.jvm.hotspot.HotSpotAgent.setupDebugger(HotSpotAgent.java:335)
at sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:304)
at sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:140)
at sun.jvm.hotspot.HSDB.attach(HSDB.java:1184)
at sun.jvm.hotspot.HSDB.access$1700(HSDB.java:53)
at sun.jvm.hotspot.HSDB$25$1.run(HSDB.java:456)
at sun.jvm.hotspot.utilities.WorkerThread$MainLoop.run(WorkerThread.java:66)
at java.base/java.lang.Thread.run(Thread.java:834)

含义是有一个 sawindbg.dll 在 jdk 的目录下找不到,因为我本地有多个 jdk ,配置环境变量的是 jdk 11 ,我在 jdk 8 的 jre 的 bin 目录下找到了这个文件,直接 copy 到 jdk 11 的bin 目录下解决此问题。

执行完成后会打开这么个界面:

深入理解可视化JVM 故障处理工具

接下来,我们写一小段测试代码:

public abstract class A {
  public void printMe() {
    System.out.println("I am A class");
  }
  public abstract void sayHello();
}

public class B extends A {
  @Override
  public void sayHello() {
    System.out.println("I am B class");
  }
}

public class HSDB_Test {
  public static void main(String[] args) throws IOException {
    A obj = new B();
    // 无意义,单纯用作卡住主线程,防止线程结束
    System.in.read();
    System.out.println(obj);
  }
}

首先在命令行中使用命令 jps -l 查看 Java 进程的 pid :

PS C:\Users\inwsy> jps -l
1648 com.geekdigging.lesson04.jvmtools.HSDB_Test
8704
9280 org.jetbrains.jps.cmdline.Launcher
14724 jdk.jcmd/sun.tools.jps.Jps
3220 org/netbeans/Main
15144
20572 org.jetbrains.jps.cmdline.Launcher
7548 sun.jvm.hotspot.HSDB

可以看到,我们刚写的测试方法的 pid 是 1648 ,在 HSDB 中点击 File > Attach to Hotspot process :

深入理解可视化JVM 故障处理工具

深入理解可视化JVM 故障处理工具

扫一扫手机访问