jstack是用来查看JVM线程快照的命令,线程快照是当前JVM线程正在执行的方法堆栈集合。使用jstack命令可以定位线程出现长时间卡顿的原因,例如死锁,死循环等。jstack还可以查看程序崩溃时生成的core文件中的stack信息。
jstack [options]
option参数解释:
-F 当使用jstack 无响应时,强制输出线程堆栈。
-m 同时输出java堆栈和c/c++堆栈信息(混合模式)
-l 除了输出堆栈信息外,还显示关于锁的附加信息
cpu占用过高问题
- 使用Process Explorer工具找到cpu占用率较高的线程
- 在thread卡中找到cpu占用高的线程id
- 线程id转换成16进制
- 使用jstack -l 查看进程的线程快照
- 线程快照中找到指定线程,并分析代码
jstack检查死锁问题
public class DeadLock {
private static Object obj1 = new Object();
private static Object obj2 = new Object();
public static void main(String[] args) {
new Thread(new Thread1()).start();
new Thread(new Thread2()).start();
}
private static class Thread1 implements Runnable{
public void run() {
synchronized (obj1){
System.out.println("Thread1 拿到了 obj1 的锁!");
try {
// 停顿2秒的意义在于,让Thread2线程拿到obj2的锁
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj2){
System.out.println("Thread1 拿到了 obj2 的锁!");
}
}
}
}
private static class Thread2 implements Runnable{
public void run() {
synchronized (obj2){
System.out.println("Thread2 拿到了 obj2 的锁!");
try {
// 停顿2秒的意义在于,让Thread1线程拿到obj1的锁
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj1){
System.out.println("Thread2 拿到了 obj1 的锁!");
}
}
}
}
}
执行指令:
jstack -l 11666
打印结果
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00007efc880062c8 (object 0x00000000ec1dc5c8, a java.lang.Object), which is held by "Thread-0" "Thread-0": waiting to lock monitor 0x00007efc88004e28 (object 0x00000000ec1dc5d8, a java.lang.Object), which is held by "Thread-1" Java stack information for the threads listed above: ===================================================
"Thread-1":
at DeadLock$Thread2.run(DeadLock.java:35)
- waiting to lock (a java.lang.Object)
- locked (a java.lang.Object) at java.lang.Thread.run(Thread.java:748)
"Thread-0":
at DeadLock$Thread1.run(DeadLock.java:19)
- waiting to lock (a java.lang.Object)
- locked (a java.lang.Object) at java.lang.Thread.run(Thread.java:748) Found 1 deadlock.