Bootstrap

20210519 使用jstack命令排查线程死锁问题

问题:  针对线上多线程死锁、阻塞,跑着跑着就卡住了;查看线上线程池的状态;

jstack主要用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。

jstack: java堆栈跟踪工具(线程快照和内存快照)

  • 执行jstack命令,将得到进程的堆栈信息。我一般使用jstack -l pid来得到长列表,显示其详细信息。

  • 有时线程挂起的时候,需要执行jstack -F pid来获取。

  • 在实际运行中,往往一次 dump的信息,还不足以确认问题。建议产生三次 dump信息,如果每次 dump都指向同一个问题,我们才确定问题的典型性。

  • 堆栈信息只是一种参考,一些正常RUNNING的线程,由于复杂网络环境和IO的影响,也是有问题的,用jstack就无法定位,需要结合对业务代码的理解。

常用命令

jps

top -H -p <pid>

jstack -l <pid>

top -H -p <pid>

1)在当前用户下,列出pid包含的所有线程。查询某个进程中所有的线程信息,cpu使用和内存。

2)线程id(十进制)和线程快照中nid相同(十六进制,操作系统级别的线程id)

3) 关注某个进程中,哪些线程的cpu和内存使用率最高,找到对应的线程快照,并且重点关注线程状态和业务代码。并且关注线程中,是否存在死锁。

 

 

1,死锁代码如下

/**
 * 测试死锁问题
 */
public class DeadLockDemo {

    public static void main(String[] args) {
        testDeadLock();
    }

    private static void testDeadLock() {
        ReentrantLock lock1 = new ReentrantLock();
        ReentrantLock lock2 = new ReentrantLock();

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                lock1.lock();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock2.lock();
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                lock2.lock();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock1.lock();
            }
        });

        thread1.setName("thread1");
        thread2.setName("thread2");

        System.out.println("启动线程");
        thread1.start();
        thread2.start();
        
    }
}

2,线程快照如下:

命令:jps获取进程编号,jstack -l 82595 >> thread.txt

使用jstack查看服务进程的线程情况

2021-05-19 15:29:10
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.291-b10 mixed mode):

"Attach Listener" #14 daemon prio=9 os_prio=31 tid=0x00007f8b2c45c800 nid=0x9c03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"DestroyJavaVM" #13 prio=5 os_prio=31 tid=0x00007f8b2c015000 nid=0x2403 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"thread2" #12 prio=5 os_prio=31 tid=0x00007f8b1c016800 nid=0x9e03 waiting on condition [0x000000
;