官网地址:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstack.html
一、介绍
The jstack command prints Java stack traces of Java threads for a specified Java process, core file, or remote debug server.
jstack
命令打印指定Java进程、核心文件或远程调试服务器上Java线程的堆栈跟踪信息。
二、用法
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)
Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message
-
jstack [-l] <pid>
用户jps
获取java进程
F:\suzao>jps -l
10788 org.jetbrains.jps.cmdline.Launcher
11064 org.jetbrains.jps.cmdline.Launcher
11976 sun.tools.jps.Jps
8712 org.jetbrains.idea.maven.server.RemoteMavenServer
jstack
查看8712进程的栈详细信息
F:\suzao>jstack -l 8712
2020-09-18 11:42:34
Full thread dump OpenJDK 64-Bit Server VM (25.152-b27 mixed mode):
"RMI RenewClean-[localhost:49530]" #18 daemon prio=5 os_prio=0 tid=0x0000000056d66000 nid=0x1a1c in Object.wait() [0x0000000057caf000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000d17aa338> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x00000000d17aa338> (a java.lang.ref.ReferenceQueue$Lock)
at sun.rmi.transport.DGCClient$EndpointEntry$RenewCleanThread.run(DGCClient.java:553)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"RMI Scheduler(0)" #17 daemon prio=5 os_prio=0 tid=0x0000000056d58800 nid=0x17ac waiting on condition [0x000000005698e000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000d17a9fa0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
三、排查死锁
- 编写死锁代码demo
public class DeadLockDemo {
public static void main(String[] args) {
DeadLock dl1 = new DeadLock(true);
DeadLock dl2 = new DeadLock(false);
Thread t1 = new Thread(dl1,"DeadLockDemo-线程1");
Thread t2 = new Thread(dl2,"DeadLockDemo-线程2");
t1.start();
t2.start();
}
static class MyLock{
public static Object obj1=new Object();
public static Object obj2=new Object();
}
static class DeadLock implements Runnable{
private boolean flag;
DeadLock(boolean flag){
this.flag = flag;
}
@Override
public void run() {
if(flag){
while (true){
synchronized (MyLock.obj1){
System.out.println(Thread.currentThread().getName()+"----if 获取obj1锁");
synchronized (MyLock.obj2){
System.out.println(Thread.currentThread().getName()+"----- if 获取obj2锁");
}
}
}
}else {
synchronized (MyLock.obj2){
System.out.println(Thread.currentThread().getName()+"----else 获取obj2锁");
synchronized (MyLock.obj1){
System.out.println(Thread.currentThread().getName()+"----- ielse获取obj1锁");
}
}
}
}
}
}
-
运行代码
代码运行最终结果造成了死锁
DeadLockDemo-线程1----- if 获取obj2锁
DeadLockDemo-线程1----if 获取obj1锁
DeadLockDemo-线程1----- if 获取obj2锁
DeadLockDemo-线程1----if 获取obj1锁
DeadLockDemo-线程2----else 获取obj2锁
- 查看死锁java进程
F:\suzao>jps -l
10092 com.suzao.DeadLockDemo
- 利用stack 查看线程
Found one Java-level deadlock:
=============================
"DeadLockDemo-线程2":
waiting to lock monitor 0x000000001be9d5e8 (object 0x000000076b359428, a java.lang.Object),
which is held by "DeadLockDemo-线程1"
"DeadLockDemo-线程1":
waiting to lock monitor 0x000000001be9d698 (object 0x000000076b359438, a java.lang.Object),
which is held by "DeadLockDemo-线程2"
Java stack information for the threads listed above:
===================================================
"DeadLockDemo-线程2":
at com.suzao.DeadLockDemo$DeadLock.run(DeadLockDemo.java:52)
- waiting to lock <0x000000076b359428> (a java.lang.Object)
- locked <0x000000076b359438> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:748)
"DeadLockDemo-线程1":
at com.suzao.DeadLockDemo$DeadLock.run(DeadLockDemo.java:44)
- waiting to lock <0x000000076b359438> (a java.lang.Object)
- locked <0x000000076b359428> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
Found one Java-level deadlock
发现一个java级别的死锁
这样我们就可以很快定位到相关问题代码
我们在使用线程时最好给每个线程都定义一个名字,方便出现问题进行定位
-
使用jvisualvm查看
打开jvisualvm
F:\suzao>jvisualvm
F:\suzao>
The launcher has determined that the parent process has a console and will reuse it for its own console output.
Closing the console will result in termination of the running program.
Use '--console suppress' to suppress console output.
Use '--console new' to create a separate console window.
jvisualvm查看线程.png
点击线程Dump查看更详细信息
jvisualvm查看线程.png
网友评论