美文网首页
Java工具初探一(jps和jstack)

Java工具初探一(jps和jstack)

作者: DH大黄 | 来源:发表于2020-01-11 19:29 被阅读0次

Java工具初探一(jps和jstack)

本文关键字:jps,jstack,堆栈信息,进程号获取

今天在学习悟空老师的视频Java并发编程-死锁方面的知识的时候,看到一些java工具的使用,于是便粗略地了解了一下。在此记个笔记,以备以后不时之需!

首先:先了解下Java工具所在的目录

${JAVA_HOME}/bin # ${JAVA_HOME}为Java的安装目录

本文档使用到了一个测试的Java类,以下便是我的测试Java类内容:

package com.hbj.learning.deadlock;

/**
 * 必然发生死锁例子
 *
 * @author hbj
 * @date 2020/1/11 16:14
 */
public class MustDeadLock implements Runnable {
    static Object lock1 = new Object();
    static Object lock2 = new Object();
    int flag = 1;

    @Override
    public void run() {
        System.out.println("flag = " + flag);
        if (flag == 1) {
            synchronized (lock1) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock2) {
                    System.out.println("线程1成功拿到锁");
                }
            }
        }
        if (flag == 0) {
            synchronized (lock2) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock1) {
                    System.out.println("线程2成功拿到锁");
                }
            }
        }
    }

    public static void main(String[] args) {
        MustDeadLock r1 = new MustDeadLock();
        MustDeadLock r2 = new MustDeadLock();
        r1.flag = 1;
        r2.flag = 0;
        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);
        t1.start();
        t2.start();
    }
}

以下的工具,使用前需要运行当前的这个Java类

1.查看当前项目/执行地Java文件的进程号(这里使用的是jps工具)

${JAVA_HOME}/bin/jps

# 执行的结果为
17584 MustDeadLock
2416
13028 Launcher
17956 RemoteMavenServer36
17260 Jps
# 此时我们便知道了MustDeadLock这个进程的进程号为17584

2.通过进程号查看各个线程调用的堆栈信息(这里使用的是jstack工具)

${JAVA_HOME}/bin/jstack 17584

# 执行的结果为
2020-01-11 19:20:26
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.161-b12 mixed mode):

"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x000000000166e800 nid=0x2098 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-1" #13 prio=5 os_prio=0 tid=0x000000001f10d800 nid=0x23d0 waiting for monitor entry [0x000000001ff3f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.hbj.learning.deadlock.MustDeadLock.run(MustDeadLock.java:37)
        - waiting to lock <0x000000076b5a5d40> (a java.lang.Object)
        - locked <0x000000076b5a5d50> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:748)

"Thread-0" #12 prio=5 os_prio=0 tid=0x000000001f10d000 nid=0x134c waiting for monitor entry [0x000000001fe3f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.hbj.learning.deadlock.MustDeadLock.run(MustDeadLock.java:25)
        - waiting to lock <0x000000076b5a5d50> (a java.lang.Object)
        - locked <0x000000076b5a5d40> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:748)

"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x000000001f012000 nid=0x2978 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #10 daemon prio=9 os_prio=2 tid=0x000000001efc6000 nid=0x4b5c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x000000001efc1000 nid=0x1e80 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000001efbd800 nid=0x17d4 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x000000001efb0000 nid=0x46e8 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001efa0800 nid=0x47a8 runnable [0x000000001f73e000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
        - locked <0x000000076b6cef68> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:161)
        at java.io.BufferedReader.readLine(BufferedReader.java:324)
        - locked <0x000000076b6cef68> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001ef73000 nid=0x3494 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001ef72000 nid=0x431c runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001ef00800 nid=0x105c in Object.wait() [0x000000001f3de000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076b408ec0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x000000076b408ec0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00000000035d9000 nid=0x748 in Object.wait() [0x000000001eedf000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076b406b68> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x000000076b406b68> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=2 tid=0x000000001cff9000 nid=0x39e4 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000000034f8800 nid=0x41e4 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00000000034fa000 nid=0x427c runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00000000034fb800 nid=0x4484 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00000000034fd000 nid=0x23e8 runnable

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00000000034ff800 nid=0x1960 runnable

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000000003501800 nid=0x4b00 runnable

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000000003504800 nid=0x3fa4 runnable

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000000003506000 nid=0x1c94 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x000000001f108800 nid=0x8b4 waiting on condition

JNI global references: 30


Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x000000001d003478 (object 0x000000076b5a5d40, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x000000001d000a88 (object 0x000000076b5a5d50, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at com.hbj.learning.deadlock.MustDeadLock.run(MustDeadLock.java:37)
        - waiting to lock <0x000000076b5a5d40> (a java.lang.Object)
        - locked <0x000000076b5a5d50> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:748)
"Thread-0":
        at com.hbj.learning.deadlock.MustDeadLock.run(MustDeadLock.java:25)
        - waiting to lock <0x000000076b5a5d50> (a java.lang.Object)
        - locked <0x000000076b5a5d40> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

# 通过这个结果,我们可以发现Thread-1和Thread-0都陷入了死锁
# Thread-1 在等待锁 <0x000000076b5a5d40> (a java.lang.Object)
# 而这个锁被 Thread-0所持有,而Thread-0在等待锁 <0x000000076b5a5d50> (a java.lang.Object)
# 而这个锁被 Thread-1所持有
# 两者都在等待切都不会释放,则出现了死锁的情况

Tips:

此处分享一个小技巧:在我们线上环境,出现死锁该如何解决

1.首先我们要保留案发现场,以便后续排查,然后立刻重启服务

2.在暂时保证了线上服务的安全后,利用刚刚保存的堆栈信息和项目的日志,排查死锁的原因,修改代码,重新发版

——————————————————————————————

此时,在保留案发现场的堆栈信息,我们便可以用到jstack的命令

jstack -l 17584 > E://17584-stacklog.txt

这里便将进程号为17584的堆栈信息保存在E盘目录下一个名叫17584-stacklog.txt的文件里了

——————————————————————————————

相关文章

网友评论

      本文标题:Java工具初探一(jps和jstack)

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