天天看点

JVM问题排查——死锁环境准备工作排查

JVM问题排查——死锁环境准备工作排查

文章目录

  • 环境
  • 准备工作
  • 排查
    • 姿势一:使用JVisualVM排查
    • 姿势二:使用Jps+Jstack

环境

JDK8

准备工作

先准备好一个死锁程序:(程序是网上随便找的)

public class DeadLock {
    public static String obj1 = "obj1";
    public static String obj2 = "obj2";
    public static void main(String[] args){
        Thread a = new Thread(new Lock1());
        Thread b = new Thread(new Lock2());
        a.start();
        b.start();
    }    
}
class Lock1 implements Runnable{
    @Override
    public void run(){
        try{
            System.out.println("Lock1 running");
            while(true){
                synchronized(DeadLock.obj1){
                    System.out.println("Lock1 lock obj1");
                    Thread.sleep(3000);//获取obj1后先等一会儿,让Lock2有足够的时间锁住obj2
                    synchronized(DeadLock.obj2){
                        System.out.println("Lock1 lock obj2");
                    }
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
class Lock2 implements Runnable{
    @Override
    public void run(){
        try{
            System.out.println("Lock2 running");
            while(true){
                synchronized(DeadLock.obj2){
                    System.out.println("Lock2 lock obj2");
                    Thread.sleep(3000);
                    synchronized(DeadLock.obj1){
                        System.out.println("Lock2 lock obj1");
                    }
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
           

运行起来,会显示如下:

Lock2 running

Lock2 lock obj2

Lock1 running

Lock1 lock obj1

此时已发生死锁。针对两个问题,我们开始排查:

  1. 哪几个线程发生了死锁
  2. 死锁发生在哪几行代码

排查

姿势一:使用JVisualVM排查

JDK8提供了一个可视化工具Jvisualvm,在jdk的bin目录下可以找到。

双击打开它:

JVM问题排查——死锁环境准备工作排查

从上图可以看到这里我们的项目DeadLock正在运行中。双击打开。

JVM问题排查——死锁环境准备工作排查

点击“线程”标签,可以看到上图。

非常醒目的“检测到死锁!”红色字样。并且可以看到下面的线程图中,Thread0和Thread1两眼的红色进度条,说明已经发生阻塞。

接下来查一下到底是哪一行代码出现了问题:

单击上图中右上角的一个按钮“线程Dump”。

此时会看到长段文字,一直往下翻,可以看到:

JVM问题排查——死锁环境准备工作排查

可以看到死锁发生的位置。有了这些信息,我们就可以去review我们的代码了。

姿势二:使用Jps+Jstack

不熟悉这些常用的JVM调优工具?传送门:

通过jps获取到我们的进程id是21036,然后利用jstack看看当前的线程快照:

输入以下:

会看到控制台输出了很多信息,直接翻到最后:

JVM问题排查——死锁环境准备工作排查

到这里就成功定位到了死锁发生的代码行。

除了上述的两种方式,其实还有很多其他办法,不过大体都是利用一些监控工具。

很多商用的监控工具功能非常全面且强大,例如Jprofiler等,这里就不多介绍了。

更多资料欢迎关注:

JVM问题排查——死锁环境准备工作排查