美文网首页
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