一、死锁分析
1、jps命令查找所进程id:
admindeMacBook-Pro-49:~ chendu$ jps
19265 Launcher
28819 Launcher
29235 Jps
28820 Concurrent
1596
2、jstack查看 Java 进程内当前时刻的线程快照,也就是每条线程正在执行的方法栈情况,用于定位线程停顿、死锁等长时间等待的问题。
jstack的帮助文档:
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
admindeMacBook-Pro-49:~ chendu$ jstack -l 28820
Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00007fe75300b8b8 (object 0x000000076acac7b8, a java.lang.String),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x00007fe75300cca8 (object 0x000000076acac7e8, a java.lang.String),
which is held by "Thread-1"
Java stack information for the threads listed above:
===================================================
"Thread-1":
at com.sample.Concurrent$2.run(Concurrent.java:34)
- waiting to lock <0x000000076acac7b8> (a java.lang.String)
- locked <0x000000076acac7e8> (a java.lang.String)
at java.lang.Thread.run(Thread.java:748)
"Thread-0":
at com.sample.Concurrent$1.run(Concurrent.java:20)
- waiting to lock <0x000000076acac7e8> (a java.lang.String)
- locked <0x000000076acac7b8> (a java.lang.String)
at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.
可以发现Thread-0的waiting to lock对象等于Thread-1的locked对象,同时Thread-1的waiting to lock对象等于Thread-0的locked对象,两个线程由于互相持有对方需要的锁而发生的阻塞现象;
例程:
package com.sample;
public class Concurrent {
private static String resource_a = "A";
private static String resource_b = "B";
public static void main(String[] args) {
deadLock();
}
public static void deadLock() {
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
synchronized (resource_a) {
System.out.println("get resource a");
try {
Thread.sleep(3000);
synchronized (resource_b) {
System.out.println("get resource b");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
synchronized (resource_b) {
System.out.println("get resource b");
synchronized (resource_a) {
System.out.println("get resource a");
}
}
}
});
threadA.start();
threadB.start();
}
}
二、死循环分析
1、jps命令查找所进程id【同上】
2、jstack查看 Java 进程内当前时刻的线程快照【同上】
例程:
package com.sample;
public class Concurrent {
@org.junit.Test
public void test(){
while (true);
}
}
admindeMacBook-Pro-49:maven-sample chendu$ jstack -l 62456|grep -A 5 "main"
"main" #1 prio=5 os_prio=31 tid=0x00007f927a804800 nid=0x2603 runnable [0x0000700005900000]
java.lang.Thread.State: RUNNABLE
at com.sample.Concurrent.test(Concurrent.java:6)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
--
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
多次使用jstack输出,发现在多次打出函数的调用栈时,可以发现程序一直处于RUNNABLE状态,并且一直在test函数的第6行,从而可以判断该程序处于死循环状态。