jstack
jstack是JVM当前时刻的线程快照,是JVM当前每一条线程正在执行的堆栈信息的集合。通过jstack命令可以获取Java应用程序运行时线程的状态、调用栈、锁状态等信息,以此来定位线程出现长时间停顿的原因,如线程死锁,线程阻塞等。
(1)命令格式
jstack [-option] pid
常用选项:
参数 | 说明 |
---|---|
-F | 当jstack指令无响应时,强制打印一个堆栈信息 |
-l | 显示关于锁的信息 |
-m | 如果调用到本地方法,显示C/C++的堆栈信息 |
-e | 打印关于线程的附加信息(较少使用) |
-h | 帮助信息 |
Extra:可以使用jps命令查找目标Java进程的进程ID
(2)案例分析
死锁案例
public class test59 {
private static Object lockA = new Object();
private static Object lockB = new Object();
public static void main(String[] args) {
new Thread(() ->{
synchronized (lockA) {
try {
System.out.println("线程1开始运行========");
Thread.sleep(2000);
} catch (InterruptedException e) {
}
synchronized (lockB) {
System.out.println("线程1运行结束========");
}
}
}).start();
new Thread(() ->{
synchronized (lockB) {
try {
System.out.println("线程2开始运行========");
Thread.sleep(2000);
} catch (InterruptedException e) {
}
synchronized (lockA) {
System.out.println("线程2结束运行========");
}
}
}).start();
System.out.println("主线程运行结束========");
}
}
运行结果:
分析步骤:
- 使用jps查找对应pid
-
使用
jstack -l [pid]
查看死锁信息信息中包含死锁具体位置和原因,便于定位问题。
CPU占用率高案例
public class test60 {
private static ExecutorService executorService = Executors.newFixedThreadPool(5);
public static void main(String[] args) {
Task task1 = new Task();
Task task2 = new Task();
executorService.execute(task1);
executorService.execute(task2);
}
public static Object lock = new Object();
static class Task implements Runnable {
public void run() {
synchronized (lock) {
long sum = 0L;
while (true) {
sum += 1;
}
}
}
}
}
分析步骤:
- 使用top命令查看进程的内存情况
- 使用
jstack [pid]
查看堆栈信息
可以发现可能存在问题的代码行。