Usage: jstack [-l] <pid> (to connect to running process) jstack -F [-m] [-l] <pid> (to connect to a hung process) jstack [-m] [-l] <executable> <core> (to connect to a core file) jstack [-m] [-l] [server_id@]<remote server IP or hostname> (to connect to a remote debug server)
"Thread-1" #14 prio=5 os_prio=0 tid=0x00000000227d2000 nid=0x21898 waiting for monitor entry [0x00000000235df000] java.lang.Thread.State: BLOCKED (on object monitor) at com.exp.App$2.run(App.java:34) - waiting to lock <0x0000000740da48c0> (a java.lang.String) - locked <0x0000000740da48f0> (a java.lang.String) at java.lang.Thread.run(Thread.java:748)
Locked ownable synchronizers: - None
"Thread-0" #13 prio=5 os_prio=0 tid=0x00000000227d1000 nid=0x23f90 waiting for monitor entry [0x00000000234df000] java.lang.Thread.State: BLOCKED (on object monitor) at com.exp.App$1.run(App.java:19) - waiting to lock <0x0000000740da48f0> (a java.lang.String) - locked <0x0000000740da48c0> (a java.lang.String) at java.lang.Thread.run(Thread.java:748)
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000002126a000 nid=0x240c4 in Object.wait() [0x00000000225df000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000740988ec0> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) - locked <0x0000000740988ec0> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:212)
Locked ownable synchronizers: - None
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000021249800 nid=0x24090 in Object.wait() [0x00000000224de000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000740986b68> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x0000000740986b68> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
"VM Periodic Task Thread" os_prio=2 tid=0x00000000227c9000 nid=0x240f8 waiting on condition
JNI global references: 1880
Found one Java-level deadlock: ============================= "Thread-1": waiting to lock monitor 0x00000000031fdbd8 (object 0x0000000740da48c0, a java.lang.String), which is held by "Thread-0" "Thread-0": waiting to lock monitor 0x00000000031fc5d8 (object 0x0000000740da48f0, a java.lang.String), which is held by "Thread-1"
Java stack information for the threads listed above: =================================================== "Thread-1": at com.exp.App$2.run(App.java:34) - waiting to lock <0x0000000740da48c0> (a java.lang.String) - locked <0x0000000740da48f0> (a java.lang.String) at java.lang.Thread.run(Thread.java:748) "Thread-0": at com.exp.App$1.run(App.java:19) - waiting to lock <0x0000000740da48f0> (a java.lang.String) - locked <0x0000000740da48c0> (a java.lang.String) at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
通过观察可以发现 Thread-0、Thread-1 两个线程均处于 BLOCKED 状态,而且堆栈信息的最后明确提示了 Found 1 deadlock.,相关锁定的代码行也都有非常明确的提示,相关提示如下:
Found one Java-level deadlock: ============================= "Thread-1": waiting to lock monitor 0x00000000031fdbd8 (object 0x0000000740da48c0, a java.lang.String), which is held by "Thread-0" "Thread-0": waiting to lock monitor 0x00000000031fc5d8 (object 0x0000000740da48f0, a java.lang.String), which is held by "Thread-1"
Java stack information for the threads listed above: =================================================== "Thread-1": at com.exp.App$2.run(App.java:34) - waiting to lock <0x0000000740da48c0> (a java.lang.String) - locked <0x0000000740da48f0> (a java.lang.String) at java.lang.Thread.run(Thread.java:748) "Thread-0": at com.exp.App$1.run(App.java:19) - waiting to lock <0x0000000740da48f0> (a java.lang.String) - locked <0x0000000740da48c0> (a java.lang.String) at java.lang.Thread.run(Thread.java:748)
OPTIONS: -h, --help this help -b, --include-blocking-thread Find the thread who is holding a lock that blocks the most number of threads. -i, --sample-interval <value> Specify the sampling interval (in ms) when calculating cpu usage. -n, --top-n-threads <value> The number of thread(s) to show, ordered by cpu utilization, -1 to show all. <id> Show thread stack
从帮助信息中可知 thread -b 可以帮我们查询阻塞时间最长的线程。
1 2 3 4 5 6 7 8
[arthas@664776]$ thread -b "Thread-0" Id=13 BLOCKED on java.lang.String@45db1404 owned by "Thread-1" Id=14 at com.exp.App$1.run(App.java:19) - blocked on java.lang.String@45db1404 - locked java.lang.String@2fa93a25 <---- but blocks 1 other threads! at java.lang.Thread.run(Thread.java:748)