jstack可用于生成JVM当前的线程快照,可快速定位线程间死锁、死循环或者线程长时间等待停顿的原因。
jstack命令格式
jstack [option] LVMID
option参数
-F : 当正常输出请求不被响应时,强制输出线程堆栈
-l : 除堆栈外,显示关于锁的附加信息
-m : 如果调用到本地方法的话,可以显示C/C++的堆栈
Linux下jstack用法
(一)找到进程号:90464
使用命令ps -ef | grep tomcat
(二)找出该进程的占用CPU的线程情况
可以看出占用CPU最高的线程号是90485
使用命令:top -Hp 90464
(三)将90485转换为16进制:16175
使用命令printf "%x\n" 90485
(四)使用jstack命令查看该线程的堆栈信息
使用命令:jstack 90464 | grep 16175
(五)Jstack检查死锁的例子
首先看一个java实例:
package com.lixin.learning.thread;
publicclassTestDeadThreadimplementsRunnable{
publicstaticObjecto1=newObject(); publicstaticObjecto2=newObject(); privatebooleanflag;
publicTestDeadThread(booleanflag){ this.flag=flag; }
@Override publicvoidrun(){ StringthreadName=Thread.currentThread().getName(); if(flag){ while(true){ synchronized(o1){ try{ Thread.sleep(1000); }catch(InterruptedExceptione){ e.printStackTrace(); } System.out.println(threadName+"get o1 lock"); synchronized(o2){ System.out.println(threadName+"get o2 lock"); } } } }else{ while(true){ synchronized(o2){ try{ Thread.sleep(1000); }catch(InterruptedExceptione){ e.printStackTrace(); } System.out.println(threadName+"get o2 lock"); synchronized(o1){ System.out.println(threadName+"get o1 lock"); } } } }
}
publicstaticvoidmain(String[]args){ TestDeadThreadthreada=newTestDeadThread(true); TestDeadThreadthreadb=newTestDeadThread(false);
Threada=newThread(threada); Threadb=newThread(threadb);
a.start(); b.start(); }
} |
输出结果:
Thread-0get o1 lock Thread-1get o2 lock |
1:线程1首先获取对象1的锁,然后睡眠1秒钟
2:线程2获取对象2的锁,也睡眠1秒钟
3:线程1睡眠时间到,想要获取对象2的锁,但是对象2的锁已经被线程2持有,则等待对象2解锁。
4:线程2睡眠时间,想要获取对象1的锁,但是对象1的锁已经被线程1持有,则等待对象1解锁。
这样线程1和线程2相互等待,进入死锁状态。
先通过jps(JVM Process Status)获取进程号
C:\Program Files\Java\jdk1.8.0_77\bin>jps -l 10736 7808 com.lixin.learning.thread.TestDeadThread 5960 sun.tools.jps.Jps |
使用jstack生成java虚拟机当前时刻的线程快照
C:\Program Files\Java\jdk1.8.0_77\bin>jstack -l 7808 > e:/a.jstack |
2017-03-14 10:12:19 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.77-b03 mixed mode):
"DestroyJavaVM" #12 prio=5 os_prio=0 tid=0x00000000024ce800 nid=0x1ac8 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers: - None
"Thread-1" #11 prio=5 os_prio=0 tid=0x0000000058b4b000 nid=0x26c8 waiting for monitor entry [0x0000000059bce000] java.lang.Thread.State: BLOCKED (on object monitor) at com.lixin.learning.thread.TestDeadThread.run(TestDeadThread.java:39) - waiting to lock <0x00000000d5cf2640> (a java.lang.Object) - locked <0x00000000d5cf2650> (a java.lang.Object) at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers: - None
"Thread-0" #10 prio=5 os_prio=0 tid=0x0000000058b48800 nid=0x2018 waiting for monitor entry [0x00000000599ce000] java.lang.Thread.State: BLOCKED (on object monitor) at com.lixin.learning.thread.TestDeadThread.run(TestDeadThread.java:25) - waiting to lock <0x00000000d5cf2650> (a java.lang.Object) - locked <0x00000000d5cf2640> (a java.lang.Object) at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers: - None
"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x0000000058ae7800 nid=0x310c runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers: - None
"C1 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x0000000058a75000 nid=0x1cb0 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers: - None
"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x0000000058a6c000 nid=0x2388 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers: - None
"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x0000000058a6b000 nid=0xb1c waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers: - None
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000058a6a000 nid=0x30fc waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers: - None
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000058a67800 nid=0x2e6c runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers: - None
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000005758b800 nid=0x309c in Object.wait() [0x0000000058a4f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000000d5c08ee0> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(Unknown Source) - locked <0x00000000d5c08ee0> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(Unknown Source) at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)
Locked ownable synchronizers: - None
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000057544800 nid=0x2708 in Object.wait() [0x00000000588cf000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000000d5c06b50> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Unknown Source) at java.lang.ref.Reference.tryHandlePending(Unknown Source) - locked <0x00000000d5c06b50> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
Locked ownable synchronizers: - None
"VM Thread" os_prio=2 tid=0x000000005753c800 nid=0x1ad4 runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x000000000263f000 nid=0x28bc runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002640800 nid=0x2b04 runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002642000 nid=0x22a0 runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002645800 nid=0x215c runnable
"VM Periodic Task Thread" os_prio=2 tid=0x0000000058b26800 nid=0x2e7c waiting on condition
JNI global references: 6
Found one Java-level deadlock: ============================= "Thread-1": waiting to lock monitor 0x000000005754b148 (object 0x00000000d5cf2640, a java.lang.Object), which is held by "Thread-0" "Thread-0": waiting to lock monitor 0x0000000057548cd8 (object 0x00000000d5cf2650, a java.lang.Object), which is held by "Thread-1"
Java stack information for the threads listed above: =================================================== "Thread-1": at com.lixin.learning.thread.TestDeadThread.run(TestDeadThread.java:39) - waiting to lock <0x00000000d5cf2640> (a java.lang.Object) - locked <0x00000000d5cf2650> (a java.lang.Object) at java.lang.Thread.run(Unknown Source) "Thread-0": at com.lixin.learning.thread.TestDeadThread.run(TestDeadThread.java:25) - waiting to lock <0x00000000d5cf2650> (a java.lang.Object) - locked <0x00000000d5cf2640> (a java.lang.Object) at java.lang.Thread.run(Unknown Source)
Found 1 deadlock.
|
可以看到jstack检查到了一个线程间死锁。