jstack
我们知道 jdk 的 bin 目录之中有很多命令行工具,这些命令主要包括用于监视虚拟机和故障处理的工具。Sun JDK 监控和故障处理工具主要有 jps、jstat、jinfo、jmap、jhat 和 jstack 等等。
jps:虚拟机进程状况工具
jstack:Java 堆栈跟踪工具
JDK 命令行
名称 | 主要作用 |
---|---|
jps | JVM Process Status Tool,显示指定系统内所有的 HotSpot 虚拟机进程 |
jstat | JVM Statistics Monitoring Tool,用于收集 HotSpot 虚拟机各方面的运行数据 |
jinfo | Configuration Info for Java,显示虚拟机配置信息 |
jmap | Memory Map for Java,生成虚拟机的内存转储快照(heapdump 文件) |
jhat | JVM Heap Dump Browser,用于分析 heapdump 文件,它会建立一个 HTTP/HTML 服务器,让用户可以在浏览器上查看分析结果 |
jstack | Stack Trace for Java,显示虚拟机的线程快照 |
jps:虚拟机进程状况工具
JDK 的很多小工具的名字都参考了 UNIX 命令的命名方式,jps(JVM Process Status Tool)是其中的典型。除了名字像 UNIX 的 ps 命令之外,它的功能也和 ps 命令类似:可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class,main() 函数所在的类)名称以及这些进程的本地虚拟机唯一 ID(Local Virtual Machine Identifier,LVMID)。虽然功能比较单一,但它是使用频率最高的 JDK 命令行工具,因为其他的 JDK 工具大多需要输入它查询到的 LVMID 来确定要监控的是哪一个虚拟机进程。对于本地虚拟机进程来说,LVMID 与操作系统的进程 ID(Process Identifter,PID)是一致的,使用 Windows 的任务管理器或者 UNIX 的 ps 命令也可以查询到虚拟机进程的 LVMID,但如果同时启动了 多个虚拟机进程,无法根据进程名称定位时,那就只能依赖 jps 命令显示主类的功能才能区分了。
jps 命令格式:
jps 可以通过 RMI 协议查询开启了 RMI 服务的远程虚拟机进程状态,hostid 为 RMI 注册表中注册的主机名。
jps 选项:
- -q
- 只输出 LVMID,省略主类的名称。
- -m
- 输出虚拟机进程启动时,传递给主类 main() 函数的参数。
- -l
- 输出主类的全名,如果进程执行的是 jar 包,输出 jar 路径。
- -v
- 输出虚拟机进程启动时 JVM 参数。
jsp 示例:
jstack:Java 堆栈跟踪工具
jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为 threaddump 或者 javacore 文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。线程出现停顿的时候通过 jstack 来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情,或者等待着什么资源。
jstack 命令格式:
jstack 选项:
- -F
- 当正常输出的请求不被响应时,强制输出线程堆栈。
- -l
- 除堆栈外,显示关于锁的附加信息。
- -m
- 如果调用到本地方法的话,可以显示 C/C++ 的堆栈。
jstack 实际使用中,若遇到 Unable to open socket file: target process not responding or HotSpot VM not loaded 的提示,则表示当前执行命令的用户和 java 进程启动的用户不一致.解决方法如下:
提示第一行显示“当前不能打开 socket file,导致不能获取目标进程的回复”。
java 程序启动后,默认(请注意是默认)会在 /tmp/hsperfdata_{user_name}
目录下以该进程的 id 为文件名新建文件,并在该文件中存储 jvm 运行的相关信息,其中的 user_name 为当前的用户名。
问题的本质是当前执行 jstack 命令用户名和 java 程序启动的用户不一致,导致当前用户打不开如上的文件,我们可以通过 ps -ef | grep java
查看相应 java 程序的启动用户后,切换到对应用户后,再执行即可。