jhsdb
jhsdb
(Java HotSpot Debugger)是在JDK 9中引入的命令行实用程序,它是服务性代理(Serviceability Agent)工具的一部分。服务性代理是一个框架,允许对运行中的Java虚拟机(JVM)或崩溃后的核心转储进行深入分析。引入jhsdb
的目的有几个:
- 统一的调试工具:在JDK 9之前,开发者需要使用不同的工具,如
jmap
、jstack
、jinfo
等来执行各种调试任务。jhsdb
将这些工具统一到一个命令行界面下,使得在不切换多个工具的情况下更容易执行广泛的调试和诊断任务。 - 增强的事后诊断:
jhsdb
提供了分析核心转储和实时进程的能力,这对事后诊断至关重要。当JVM崩溃时,开发者需要了解崩溃时JVM的状态,这一点尤其有用。 - 高级分析能力:使用
jhsdb
,开发者可以执行高级分析,如检查堆、分析内存使用情况和获取线程堆栈跟踪。它还允许使用内置的命令行调试器(CLD)来调试Java进程,这是一个类似于gdb
的基于文本的界面。 - 跨平台一致性:
jhsdb
旨在在不同平台上保持一致的工作,为在各种操作系统上进行诊断提供了标准化的方法。 - 与HotSpot JVM集成:由于
jhsdb
是为HotSpot JVM量身定制的,它可以利用HotSpot的内部特性来提供有关JVM内部的详细信息,这对于性能调优和解决复杂问题非常宝贵。 - 可访问性:通过包含在JDK中,
jhsdb
可以立即供所有Java开发者使用,无需额外下载或安装。 - 可脚本化:作为命令行工具,
jhsdb
可以轻松地编写脚本并集成到自动化的调试和诊断工作流中,这对于持续集成和部署管道非常有益。
总的来说,JDK 9中引入jhsdb
的目的是通过提供一个强大而多功能的JVM诊断和调试工具来改善开发者体验,从而增强分析和解决Java应用程序中复杂问题的能力。
实践
linux 系统现在有一个正在运行的 Java 程序, 进程号是 256487
, 却遇到了下面的错误
$ jhsdb jmap --pid 256487
Attaching to process ID 256487, please wait...
ERROR: ptrace(PTRACE_ATTACH, ..) failed for 256487: Operation not permitted
Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 256487: Operation not permitted
sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 256487: Operation not permitted
这是因为 ptrace 权限的问题. 查看 /proc/sys/kernel/yama/ptrace_scope
可以看到里面的值是 1
, 改成 0
就好了
$ cat /proc/sys/kernel/yama/ptrace_scope
1
$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
0
$ jhsdb jmap --pid 256487 # as pmap output
Attaching to process ID 256487, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 11.0.22+7-post-Ubuntu-0ubuntu222.04.1
0x0000563f4efe6000 14K /usr/lib/jvm/java-11-openjdk-amd64/bin/java
0x00007fe2671ba000 44K /usr/lib/jvm/java-11-openjdk-amd64/lib/libzip.so
0x00007fe2671c5000 66K /usr/lib/x86_64-linux-gnu/libresolv.so.2
0x00007fe2671d9000 22K /usr/lib/x86_64-linux-gnu/libkeyutils.so.1.9
0x00007fe2671e0000 50K /usr/lib/x86_64-linux-gnu/libkrb5support.so.0.1
0x00007fe2671ee000 18K /usr/lib/x86_64-linux-gnu/libcom_err.so.2.1
0x00007fe2671f4000 178K /usr/lib/x86_64-linux-gnu/libk5crypto.so.3.1
0x00007fe267223000 808K /usr/lib/x86_64-linux-gnu/libkrb5.so.3.3
0x00007fe2672ee000 330K /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2.2
0x00007fe267342000 178K /usr/lib/x86_64-linux-gnu/libtirpc.so.3.0.0
0x00007fe267370000 91K /usr/lib/x86_64-linux-gnu/libnsl.so.2.0.1
0x00007fe26738a000 54K /usr/lib/x86_64-linux-gnu/libnss_nis.so.2.0.0
0x00007fe267399000 42K /usr/lib/x86_64-linux-gnu/libnss_compat.so.2
0x00007fe2673b8000 39K /usr/lib/jvm/java-11-openjdk-amd64/lib/libjimage.so
0x00007fe2673c1000 213K /usr/lib/jvm/java-11-openjdk-amd64/lib/libjava.so
0x00007fe2673ef000 14K /usr/lib/x86_64-linux-gnu/librt.so.1
0x00007fe2674f4000 122K /usr/lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007fe267514000 918K /usr/lib/x86_64-linux-gnu/libm.so.6
0x00007fe2675fb000 2207K /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30
0x00007fe267827000 22708K /usr/lib/jvm/java-11-openjdk-amd64/lib/server/libjvm.so
0x00007fe268afc000 2168K /usr/lib/x86_64-linux-gnu/libc.so.6
0x00007fe268d25000 80K /usr/lib/jvm/java-11-openjdk-amd64/lib/jli/libjli.so
0x00007fe268d38000 106K /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
0x00007fe268d54000 67K /usr/lib/jvm/java-11-openjdk-amd64/lib/libverify.so
0x00007fe268d67000 235K /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
$ jhsdb -h
clhsdb command line debugger
hsdb ui debugger
debugd --help to get more information
jstack --help to get more information
jmap --help to get more information
jinfo --help to get more information
jsnap --help to get more information
$ jhsdb jmap --help
$ jhsdb jmap --binaryheap --pid 274471
Attaching to process ID 274471, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 11.0.22+7-post-Ubuntu-0ubuntu222.04.1
heap written to heap.bin