概念:查看jvm中 线程发生问题的几种方式,这里以死锁为例
1.jps+jstack -l [pid]
测试代码
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @ClassName DeathLockTest
* @Description TODO
* @Author zxr
* @Date 2023/1/3
*/
public class DeathLockTest {
private static Lock lock1 = new ReentrantLock();
private static Lock lock2 = new ReentrantLock();
public static void deathLock() {
Thread t1 = new Thread() {
@Override
public void run() {
try {
lock1.lock();
System.out.println(Thread.currentThread().getName() + " get the lock1");
Thread.sleep(1000);
lock2.lock();
System.out.println(Thread.currentThread().getName() + " get the lock2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
try {
lock2.lock();
System.out.println(Thread.currentThread().getName() + " get the lock2");
Thread.sleep(1000);
lock1.lock();
System.out.println(Thread.currentThread().getName() + " get the lock1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
//设置线程名字,方便分析堆栈信息
t1.setName("mythread-jay");
t2.setName("mythread-tianluo");
t1.start();
t2.start();
}
public static void main(String[] args) {
deathLock();
}
}
使用jps查看可运行的java程序
前面的数值就是我们代码的进程pid
之后再通过jstack -l [pid] 查看进程的堆栈信息
jstack -l 45624
继续往下找到出问题的地方
在这里就可以看到 出问题的两个线程了,分别为:mythread-tianluo,mythread-jay;
继续往下查看 是出了啥问题。
这里可以看到线程deadlock(死锁) 了
继续看详情
红线部分:发生死锁位置
绿线部分:可以看出是在等待一秒之后另外有另一个线程获取资源,重而产生了死锁
这里使用jps 和 jstack -l [pid] 命令查询的
也可以直接使用jconsole进行查看
2.jconsole
选择进程为:45624的
选择线程点击检测死锁
能够将死锁的线程检测出来
分别点击两个线程,看死锁发生在哪个位置,和上面看到的是否一致
可以看到分别为38,24 和上面检测出的是一致的。
3.jvisualvm
选择40268
展开查看
这里已经将死锁线程检测出来了,点击右边线程dump
查看详情
同样是38,24 这里分析和上面两个一样的。
在做jvm时,根据所处的开发环境做选择就可以了。
还原死锁
这里还原死锁真相
挺有意思,互相获取,又都不放手,导致的死锁。