jstack(stack trace) 用于生成虛機當(dāng)前的線程快照乓梨,線程快照就是每個線程正在執(zhí)行的方法堆棧的集合。
生成線程快照的目的就是定位線程出現(xiàn)長時間停頓的原因玄妈,如線程間死鎖搔预、死循環(huán)、請求外部資源等敢课。
命令格式:
jstack 選項 進程ID
選項說明:
選項 | 作用 |
---|---|
-F | 當(dāng)正常輸出的請求不被響應(yīng)時,強制輸出線程堆棧 |
-l | 除堆棧外绷杜,顯示關(guān)于鎖的附加信息 |
-m | 如果調(diào)用到本地方法的話翎猛,可以顯示C/C++堆棧 |
文檔:
https://docs.oracle.com/javase/7/docs/technotes/tools/share/jstack.html
示例:
$ jstack 1409
可以看到線程ID、狀態(tài)接剩、等待的資源等信息切厘。
死鎖示例:
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
可以看到死鎖信息了懊缺。