4.2.6 jstack:Java堆栈跟踪工具

4.2.6 jstack:Java堆栈跟踪工具

jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因线程出现停顿时通过jstack来查看各个线程的调用堆栈, 就可以获知没有响应的线程到底在后台做些什么事情,或者等待着什么资源
jstack命令格式:

1
jstack [ option ] vmid

option选项的合法值与具体含义如表4-4所示。
表4-4 jstack工具主要选项

表4-4 jstack工具主要选项

image-20210917113422865

代码清单4-4是使用jstack查看Eclipse线程堆栈的例子,例子中的3500是通过jps命令查询到的LVMID。

代码清单4-4 使用jstack查看线程堆栈(部分结果)

1
2
3
4
5
6
7
8
9
10
11
12
13
jstack -l 3500 
2010-11-19 23:11:26
Full thread dump Java HotSpot(TM) 64-Bit Server VM (17.1-b03 mixed mode):
"[ThreadPool Manager] - Idle Thread" daemon prio=6 tid=0x0000000039dd4000 nid= 0xf50 in Object.wait() [0x000000003c96f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000016bdcc60> (a org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor)
at java.lang.Object.wait(Object.java:485)
at org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor.run (Executor. java:106)
- locked <0x0000000016bdcc60> (a org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor)

Locked ownable synchronizers:
- None

从JDK 5起,java.lang.Thread类新增了一个getAllStackTraces()方法用于获取虚拟机中所有线程的StackTraceElement对象。使用这个方法可以通过简单的几行代码完成jstack的大部分功能,在实际项目中不妨调用这个方法做个管理员页面,可以随时使用浏览器来查看线程堆栈,如代码清单4-5所示,这也算是笔者的一个小经验。

代码清单4-5 查看线程状况的JSP页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<%@ page import="java.util.Map" %>
<html>
<head><title>服务器线程信息</title></head>
<body>
<pre> <% for (Map.Entry<Thread, StackTraceElement[]> stackTrace : Thread.getAllStack - Traces().entrySet()) {
Thread thread = (Thread) stackTrace.getKey();
StackTraceElement[] stack = (StackTraceElement[]) stackTrace.getValue();
if (thread.equals(Thread.currentThread())) {
continue;
}
out.print("\n线程:" + thread.getName() + "\n");
for (StackTraceElement element : stack) {
out.print("\t" + element + "\n");
}
} %></pre>
</body>
</html>