jstack实战死循环与死锁

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来定位死锁并解决问题。

你可能感兴趣的:(jstack实战死循环与死锁)