美文网首页
JVM调优常用指令之jstack

JVM调优常用指令之jstack

作者: 有梦想的虫子_2018 | 来源:发表于2020-09-18 12:02 被阅读0次

官网地址: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

相关文章

网友评论

      本文标题:JVM调优常用指令之jstack

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