jstack可以打印jvm内所有的线程,利用jstack可以排除程序运行时出现的死循环或者死锁问题。
1、实战死循环
1、编写测试代码
public class TestDeadLoop {
public static void main(String[] args) {
while (true){
System.out.println("deadloop");
}
}
}
2、在Linux中,可以通过top命令找出java进程中cpu利用率特别高的那个线程
top -p [pid] -H
top命令
在上图中,cpu利用率最高的线程pid是30712。
而在Windows中,可以使用plist命令
plist命令
在上图中,Tid为20240的Cswtch达到了6496,将20240转为16进制,为4f10,记住这个数字,后面有用。
3、使用jstack打印所有线程,保存到指定文件
jstack 20240 > 20240.txt
打开文件,搜索4f10,即可找到出问题的线程的堆栈了
线程信息
这样,就可以找出死循环的那个线程在做什么事情了~
2、实战死锁
1、编写测试代码
public static void main(String[] args) {
Object lock1 = new Object();
Object lock2 = new Object();
new Thread(() -> {
synchronized (lock1){
try {
Thread.sleep(1000);
synchronized (lock2){
System.out.println("get lock 1 and lock 2");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "thread-1").start();
new Thread(() -> {
synchronized (lock2){
try {
Thread.sleep(1000);
synchronized (lock1){
System.out.println("get lock 1 and lock 2");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "thread-2").start();
}
2、运行代码,发现程序一直没有运行结束
3、在这里程序的进程id为11704,执行
jstack 11704> 11704.txt
,得到堆栈信息
"thread-2" #15 prio=5 os_prio=0 tid=0x000000001b41d000 nid=0xfa78 waiting for monitor entry [0x000000001bcce000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.tony.springboot.spring.TestDeadLock.lambda$main$1(TestDeadLock.java:28)
- waiting to lock <0x00000000d65128d8> (a java.lang.Object)
- locked <0x00000000d65128e8> (a java.lang.Object)
at com.tony.springboot.spring.TestDeadLock$$Lambda$2/41903949.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"thread-1" #14 prio=5 os_prio=0 tid=0x000000001b417800 nid=0xee2c waiting for monitor entry [0x000000001bbce000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.tony.springboot.spring.TestDeadLock.lambda$main$0(TestDeadLock.java:14)
- waiting to lock <0x00000000d65128e8> (a java.lang.Object)
- locked <0x00000000d65128d8> (a java.lang.Object)
at com.tony.springboot.spring.TestDeadLock$$Lambda$1/483422889.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
可以看出,thread-1获得了0x00000000d65128d8这把锁,等待0x00000000d65128e8这把锁,而thread-2获得了0x00000000d65128e8这把锁,等待0x00000000d65128d8这把锁。从这里就可以判断出,程序内部发生了死锁。
另外,翻到11704.txt文件的最下面,可以看到如下信息:
Found one Java-level deadlock:
=============================
"thread-2":
waiting to lock monitor 0x00000000183e3638 (object 0x00000000d65128d8, a java.lang.Object),
which is held by "thread-1"
"thread-1":
waiting to lock monitor 0x00000000183df598 (object 0x00000000d65128e8, a java.lang.Object),
which is held by "thread-2"
Java stack information for the threads listed above:
===================================================
"thread-2":
at com.tony.springboot.spring.TestDeadLock.lambda$main$1(TestDeadLock.java:28)
- waiting to lock <0x00000000d65128d8> (a java.lang.Object)
- locked <0x00000000d65128e8> (a java.lang.Object)
at com.tony.springboot.spring.TestDeadLock$$Lambda$2/41903949.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
"thread-1":
at com.tony.springboot.spring.TestDeadLock.lambda$main$0(TestDeadLock.java:14)
- waiting to lock <0x00000000d65128e8> (a java.lang.Object)
- locked <0x00000000d65128d8> (a java.lang.Object)
at com.tony.springboot.spring.TestDeadLock$$Lambda$1/483422889.run(Unknown Source)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
jstask帮我们找出了这个死锁。所以,我们可以通过jstack来定位死锁并解决问题。
网友评论