美文网首页
jstack命令使用,死锁分析

jstack命令使用,死锁分析

作者: xiaohei_e853 | 来源:发表于2022-03-28 11:13 被阅读0次
import java.io.IOException;

public class JStackDemo1 {
    public static void main(String[] args) {
        while (true) {
            //Do Nothing
        }
    }
}

$ jps
18464 Launcher
19600 Jps
5744
3896 Program
1148 JStackDemo1

输出如下信息

$ jstack 1148
2022-03-15 21:58:11
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode):

"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x000000001a1d0800 nid=0x1764 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x0000000019b8f000 nid=0x980 waiting on condition [0x0000000000
000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x0000000019b3f000 nid=0x1f20 waiting on condition [0x000000000
0000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x0000000019ac3000 nid=0x3c94 waiting on condition [0x000000000
0000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x0000000019b26800 nid=0x41d8 runnable [0x0000000019ebe000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
        - locked <0x00000000d6185420> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:161)
        at java.io.BufferedReader.readLine(BufferedReader.java:324)
        - locked <0x00000000d6185420> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:47)

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000019803800 nid=0x48f0 waiting on condition [0x000000000000
0000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000018476800 nid=0x4024 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x00000000038d9800 nid=0x1d8c in Object.wait() [0x00000000197be000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d5c08ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
        - locked <0x00000000d5c08ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00000000038d6000 nid=0x3d24 in Object.wait() [0x00000000196bf
000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d5c06bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x00000000d5c06bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"main" #1 prio=5 os_prio=0 tid=0x00000000037e6800 nid=0x3d90 runnable [0x00000000035df000]
   java.lang.Thread.State: RUNNABLE
        at test.JStackDemo1.main(JStackDemo1.java:5)

"VM Thread" os_prio=2 tid=0x0000000018417800 nid=0x624 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000000037fc000 nid=0x250c runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00000000037fd800 nid=0x4c54 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00000000037ff000 nid=0x446c runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000003800800 nid=0x4b08 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x000000001a23b800 nid=0x41b0 waiting on condition

JNI global references: 12

重点关注以下的输出,用户线程的第五行

"main" #1 prio=5 os_prio=0 tid=0x00000000037e6800 nid=0x3d90 runnable [0x00000000035df000]
   java.lang.Thread.State: RUNNABLE
        at test.JStackDemo1.main(JStackDemo1.java:5)

以及下面的输出

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00000000038d6000 nid=0x3d24 in Object.wait() [0x00000000196bf
000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d5c06bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x00000000d5c06bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

线程锁住了0x00000000d5c06bf8,又等待0x00000000d5c06bf8,已经死锁了

补充一下线程的知识

image.png

Java语言定义了6种线程池状态:

New:创建后尚未启动的线程处于这种状态,不会出现在Dump中。
-RUNNABLE:包括Running和Ready。线程开启start()方法,会进入该状态,在虚拟机内执行的。
-Waiting:无限的等待另一个线程的特定操作。
-Timed Waiting:有时限的等待另一个线程的特定操作。
-阻塞(Blocked):在程序等待进入同步区域的时候,线程将进入这种状态,在等待监视器锁。
-结束(Terminated):已终止线程的线程状态,线程已经结束执行。

Dump文件的线程状态一般其实就以下3种:

-RUNNABLE,线程处于执行中
-BLOCKED,线程被阻塞
-WAITING,线程正在等待

Monitor 监视锁

因为Java程序一般都是多线程运行的,Java多线程跟监视锁环环相扣,所以我们分析线程状态时,也需要回顾一下Monitor监视锁知识。

有关于线程同步关键字Synchronized与监视锁的爱恨情仇,有兴趣的伙伴可以看一下我这篇文章 Synchronized解析——如果你愿意一层一层剥开我的心

Monitor的工作原理图如下:

image.png

线程想要获取monitor,首先会进入Entry Set队列,它是Waiting Thread,线程状态是Waiting for monitor entry。
当某个线程成功获取对象的monitor后,进入Owner区域,它就是Active Thread。
如果线程调用了wait()方法,则会进入Wait Set队列,它会释放monitor锁,它也是Waiting Thread,线程状态in Object.wait()
如果其他线程调用 notify() / notifyAll() ,会唤醒Wait Set中的某个线程,该线程再次尝试获取monitor锁,成功即进入Owner区域。

Dump 文件分析关注重点

  • runnable,线程处于执行中
  • deadlock,死锁(重点关注)
  • blocked,线程被阻塞 (重点关注)
  • Parked,停止
  • locked,对象加锁
  • waiting,线程正在等待
  • waiting to lock 等待上锁
  • Object.wait(),对象等待中
  • waiting for monitor entry 等待获取监视器(重点关注)
  • Waiting on condition,等待资源(重点关注),最常见的情况是线程在等待网络的读写

链接:https://juejin.cn/post/6844904152850497543

相关文章

  • jstack命令使用,死锁分析

    输出如下信息 重点关注以下的输出,用户线程的第五行 以及下面的输出 线程锁住了0x00000000d5c06bf8...

  • 分析程序死锁及定位

    检测程序死锁 可以使用jstack命令, jstack you_pid进程的pid可以在任务管理器中找到,你也可以...

  • jstack命令解析

    jstack用法 jstack查看输出 jstack统计线程数 jstack检测死锁 死锁代码 死锁日志 jsta...

  • 死锁排查

    java 自带了工具 bin目录下 1、使用jps定位进程号 命令 jps -l 2、使用jstack查看死锁问题

  • jstack使用

    使用jstack分析指定应用线程使用异常排除。 使用jstack命令dump线程信息,例如查看Pid为3117的进...

  • JVM源码分析之消失的死锁

    问题描述 如果java层面发生了死锁,当我们使用jstack命令的时候其实是可以将死锁的信息给dump出来的,在d...

  • 消失的死锁

    问题描述 如果java层面发生了死锁,当我们使用jstack命令的时候其实是可以将死锁的信息给dump出来的,在d...

  • JVM常用命令之-----jstack

    Jstack jstack命令主要用于调试java程序运行过程中的线程堆栈信息,可以用于检测死锁,进程耗用cpu过...

  • jstack找到java死锁线程信息

    首先熟悉一下jstack命令的用法,如下图: 编写模拟死锁的java代码,如下: 使用jps找到执行代码的进程ID...

  • jstack的使用

    jstack命令主要打印指定Java进程的线程堆栈跟踪信息。它是一个很有用的命令。 检测死锁 编写一个导致死锁的简...

网友评论

      本文标题:jstack命令使用,死锁分析

      本文链接:https://www.haomeiwen.com/subject/lsqudrtx.html