jstack(stack trace) 用于生成虚机当前的线程快照,线程快照就是每个线程正在执行的方法堆栈的集合。
生成线程快照的目的就是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源等。
命令格式:
jstack 选项 进程ID
选项说明:
选项 | 作用 |
---|---|
-F | 当正常输出的请求不被响应时,强制输出线程堆栈 |
-l | 除堆栈外,显示关于锁的附加信息 |
-m | 如果调用到本地方法的话,可以显示C/C++堆栈 |
文档:
https://docs.oracle.com/javase/7/docs/technotes/tools/share/jstack.html
示例:
$ jstack 1409
可以看到线程ID、状态、等待的资源等信息。
死锁示例:
public class DeadlockDemo {
public static void main(String[] args) {
DieLock d1 = new DieLock(true);
DieLock d2 = new DieLock(false);
Thread t1 = new Thread(d1);
Thread t2 = new Thread(d2);
t1.start();
t2.start();
}
}
class MyLock {
public static Object obj1 = new Object();
public static Object obj2 = new Object();
}
class DieLock implements Runnable {
private boolean flag;
DieLock(boolean flag) {
this.flag = flag;
}
public void run() {
if (flag) {
while (true) {
synchronized (MyLock.obj1) {
System.out.println(Thread.currentThread().getName() + "....if...obj1...");
synchronized (MyLock.obj2) {
System.out.println(Thread.currentThread().getName() + ".....if.....obj2.....");
}
}
}
} else {
while (true) {
synchronized (MyLock.obj2) {
System.out.println(Thread.currentThread().getName() + "....else...obj2...");
synchronized (MyLock.obj1) {
System.out.println(Thread.currentThread().getName() + ".....else.....obj1.....");
}
}
}
}
}
}
运行后会锁死,查看线程状况:
# 找出死锁示例的线程ID
$ jps
# 查看线程信息
$ jstack
可以看到死锁信息了。