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的文件里了
——————————————————————————————
网友评论