作用:查看Java线程的调用堆栈,生成Java虚拟机当前时刻的线程快照(Java虚拟机内每一条线程正在执行的方法堆栈集合),用来分析线程问题。
用法:jstack <options> [<pid>] [<executable> <core>] [server_id@]<remote server IP or hostname>
选项:
-F:强制dump线程栈信息
-l:长列表,打印关于锁的附加信息。当-l选项是出现提示如下图信息的时候,需要使用-F参数强制dump线程堆栈信息
-m:打印Java和native框架的所有栈信息
先熟悉一下线程的状态
NEW:未启动的。不会出现在Dump中
RUNNABLE:运行状态,对应RUNNABLE
BLOCKED:阻塞并等待监视器锁状态,此时在进入区等待
WATING:无限期等待另一个线程执行特定操作,对应输出的in Object.wait()
TIMED_WATING:有时限的等待另一个线程的特定操作对应输出的in Object.wait()
TERMINATED:已退出的状态
SLEEPING:线程休眠,调用了Thread.sleep()
下面通过编写的一个程序来分析jstack命令的使用以及输出解释,使用-l打印Java和native信息
死锁分析:
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode):
"DestroyJavaVM" #15 prio=5 os_prio=0 tid=0x00000000023f9800 nid=0x1128 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
//DeadLock-02线程想要执行第41行的时候阻塞,当前锁资源0x00000000d6211bd8,等待资源0x00000000d6211bc8
"DeadLock-02" #14 prio=5 os_prio=0 tid=0x0000000058caa000 nid=0x1d54 waiting for monitor entry [0x0000000059e4f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at learn.demo.JStackDemo$DeadLock.run(JStackDemo.java:41)
- waiting to lock <0x00000000d6211bc8> (a java.lang.Object)
- locked <0x00000000d6211bd8> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
//DeadLock-01线程想要执行第32行的时候阻塞,当前锁资源0x00000000d6211bc8,等待资源0x00000000d6211bd8
"DeadLock-01" #13 prio=5 os_prio=0 tid=0x0000000058c8d000 nid=0x1dac waiting for monitor entry [0x000000005931f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at learn.demo.JStackDemo$DeadLock.run(JStackDemo.java:32)
- waiting to lock <0x00000000d6211bd8> (a java.lang.Object)
- locked <0x00000000d6211bc8> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"Service Thread" #12 daemon prio=9 os_prio=0 tid=0x0000000058afc000 nid=0x2648 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C1 CompilerThread2" #11 daemon prio=9 os_prio=2 tid=0x0000000058ae5000 nid=0x1900 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread1" #10 daemon prio=9 os_prio=2 tid=0x0000000058ae0800 nid=0x1294 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"C2 CompilerThread0" #9 daemon prio=9 os_prio=2 tid=0x0000000058ada000 nid=0x2248 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"JDWP Command Reader" #8 daemon prio=10 os_prio=0 tid=0x00000000589e4800 nid=0x2b10 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"JDWP Event Helper Thread" #7 daemon prio=10 os_prio=0 tid=0x00000000589e1000 nid=0xd70 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"JDWP Transport Listener: dt_socket" #6 daemon prio=10 os_prio=0 tid=0x00000000589d2800 nid=0x26d8 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000057502000 nid=0xce8 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000005750f800 nid=0xdb8 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
//Finalizer守护线程锁在资源0x00000000d5d08ec8,等待资源0x00000000d5d08ec8。
//为什么同时锁住的等待同一个资源?
//线程的执行中,先获得了这个对象的 Monitor(对应于 locked <0x00000000d5d08ec8>)。
//当执行到 obj.wait(), 线程即放弃了 Monitor的所有权,进入 “wait set”队列(对应于 waiting on <0x00000000d5d08ec8> )
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x00000000574eb000 nid=0x2684 in Object.wait() [0x00000000589ae000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d5d08ec8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x00000000d5d08ec8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
Locked ownable synchronizers:
- None
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00000000574a3800 nid=0x27b4 in Object.wait() [0x000000005887e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d5d06b68> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
- locked <0x00000000d5d06b68> (a java.lang.ref.Reference$Lock)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=2 tid=0x000000005749c000 nid=0xb5c runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x000000000240e000 nid=0x17f0 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x000000000240f800 nid=0x296c runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002411000 nid=0x2548 runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002414800 nid=0x29e4 runnable
"VM Periodic Task Thread" os_prio=2 tid=0x0000000058c0b000 nid=0x21ac waiting on condition
JNI global references: 1655
//DeadLock-01在想要执行第32行的时候,当前锁住了资源<0x00000000d6211bc8>,但是他在等待资源<0x00000000d6211bd8>
//DeadLock-02在想要执行第27行的时候,当前锁住了资源<0x00000000d6211bd8>,但是他在等待资源<0x00000000d6211bc8>
//由于这两个线程都持有资源,并且都需要对方的资源,所以造成了死锁。 然后通过改写代码解决这个死锁
Found one Java-level deadlock:
=============================
"DeadLock-02":
waiting to lock monitor 0x00000000574a7cb8 (object 0x00000000d6211bc8, a java.lang.Object),
which is held by "DeadLock-01"
"DeadLock-01":
waiting to lock monitor 0x00000000574aa6a8 (object 0x00000000d6211bd8, a java.lang.Object),
which is held by "DeadLock-02"
Java stack information for the threads listed above:
===================================================
"DeadLock-02":
at learn.demo.JStackDemo$DeadLock.run(JStackDemo.java:41)
- waiting to lock <0x00000000d6211bc8> (a java.lang.Object)
- locked <0x00000000d6211bd8> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
"DeadLock-01":
at learn.demo.JStackDemo$DeadLock.run(JStackDemo.java:32)
- waiting to lock <0x00000000d6211bd8> (a java.lang.Object)
- locked <0x00000000d6211bc8> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
Found 1 deadlock.
关于多线程
多线程的讲解这里先不介绍,否则篇幅太长。可以看一下《并发编程的艺术》或自行学习