给你的Java程序拍个片子吧:jstack命令解析
2021-01-24 13:13
标签:jstack 先来 代码 RoCE 使用 线程 lock java进程 一半 如果有一天,你的Java程序长时间停顿,也许是它病了,需要用jstack拍个片子分析分析,才能诊断具体什么病症,是死锁综合征,还是死循环等其他病症,本文我们一起来学习jstack命令~ jstack是JVM自带的Java堆栈跟踪工具,它用于打印出给定的java进程ID、core file、远程调试服务的Java堆栈信息. jstack 命令格式如下 最常用的是 option参数说明如下: jstack用于生成线程快照的,我们分析线程的情况,需要复习一下线程状态吧,拿小凳子坐好,复习一下啦~ Java语言定义了6种线程池状态: Dump文件的线程状态一般其实就以下3种: 因为Java程序一般都是多线程运行的,Java多线程跟监视锁环环相扣,所以我们分析线程状态时,也需要回顾一下Monitor监视锁知识。 有关于线程同步关键字Synchronized与监视锁的爱恨情仇,有兴趣的伙伴可以看一下我这篇文章 Monitor的工作原理图如下: 死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法进行下去。 先来看一段会产生死锁的Java程序,源码如下: 运行结果: “mythread-jay"线程堆栈信息分析如下: 来个导致CPU过高的demo程序,一个死循环,哈哈~ 在服务器上,我们可以通过top命令查看各个进程的cpu使用情况,它默认是按cpu使用率由高到低排序的 通过top -Hp 21340可以查看该进程下,各个线程的cpu使用情况,如下: 通过top命令定位到cpu占用率较高的线程之后,接着使用jstack pid命令来查看当前java进程的堆栈状态, 其实,前3个步骤,堆栈信息已经出来啦。但是一般在生成环境,我们可以把这些堆栈信息打到一个文件里,再回头仔细分析哦~ 我们把占用cpu资源较高的线程pid(本例子是21350),将该pid转成16进制的值 这个时候,可以去检查代码是否有问题啦~ 当然,也建议隔段时间再执行一次stack命令,再一份获取thread dump,毕竟两次拍片结果(jstack)对比,更准确嘛~ 给你的Java程序拍个片子吧:jstack命令解析 标签:jstack 先来 代码 RoCE 使用 线程 lock java进程 一半 原文地址:https://www.cnblogs.com/jay-huaxiao/p/12865552.html前言
jstack 的功能
jstack prints Java stack traces of Java threads for a given Java process or
core file or a remote debug server.
如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。jstack用法
jstack [ option ] pid
jstack [ option ] executable core
jstack [ option ] [server-id@]remote-hostname-or-IP
jstack [option]
选项
作用
-F
当正常输出的请求不被响应时,强制输出线程堆栈
-m
如果调用到本地方法的话,可以显示C/C++的堆栈
-l
除堆栈外,显示关于锁的附加信息,在发生死锁时可以用jstack -l pid来观察锁持有情况
线程状态等基础回顾
线程状态简介
Monitor 监视锁
Synchronized解析——如果你愿意一层一层剥开我的心
Dump 文件分析关注重点
实战案例1:jstack 分析死锁问题
什么是死锁?
如何用如何用jstack排查死锁问题
/**
* Java 死锁demo
*/
public class DeathLockTest {
private static Lock lock1 = new ReentrantLock();
private static Lock lock2 = new ReentrantLock();
public static void deathLock() {
Thread t1 = new Thread() {
@Override
public void run() {
try {
lock1.lock();
System.out.println(Thread.currentThread().getName() + " get the lock1");
Thread.sleep(1000);
lock2.lock();
System.out.println(Thread.currentThread().getName() + " get the lock2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
try {
lock2.lock();
System.out.println(Thread.currentThread().getName() + " get the lock2");
Thread.sleep(1000);
lock1.lock();
System.out.println(Thread.currentThread().getName() + " get the lock1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
//设置线程名字,方便分析堆栈信息
t1.setName("mythread-jay");
t2.setName("mythread-tianluo");
t1.start();
t2.start();
}
public static void main(String[] args) {
deathLock();
}
}
显然,线程jay和线程tianluo都是只执行到一半,就陷入了阻塞等待状态~jstack排查Java死锁步骤
在终端中输入jsp查看当前运行的java程序
通过使用 jps 命令获取需要监控的进程的pid,我们找到了23780 DeathLockTest
使用 jstack -l pid 查看线程堆栈信息
由上图,可以清晰看到死锁信息:
还原死锁真相
“mythread-tianluo"线程堆栈信息分析如下:
实战案例2:jstack 分析CPU过高问题
/**
* 有个导致CPU过高程序的demo,死循环
*/
public class JstackCase {
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;
}
}
}
}
}
jstack 分析CPU过高步骤
1.top
由上图中,我们可以找出pid为21340的java进程,它占用了最高的cpu资源,凶手就是它,哈哈!2. top -Hp pid
可以发现pid为21350的线程,CPU资源占用最高,嘻嘻,小本本把它记下来,接下来拿jstack给它拍片子3. jstack pid
jstack 21350
后,内容如下:4. jstack -l [PID] >/tmp/log.txt
5. 分析堆栈信息
在thread dump中,每个线程都有一个nid,我们找到对应的nid(5366),发现一直在跑(24行)参考与感谢
个人公众号
文章标题:给你的Java程序拍个片子吧:jstack命令解析
文章链接:http://soscw.com/index.php/essay/46327.html