dw网站怎么做点击图片放大,电视剧怎么做短视频网站,seo属于技术还是营销,2345浏览器网页版入口前言
如果有一天#xff0c;你的Java程序长时间停顿#xff0c;也许是它病了#xff0c;需要用jstack拍个片子分析分析#xff0c;才能诊断具体什么病症#xff0c;是死锁综合征#xff0c;还是死循环等其他病症#xff0c;本文我们一起来学习jstack命令~
jstack 的功…前言
如果有一天你的Java程序长时间停顿也许是它病了需要用jstack拍个片子分析分析才能诊断具体什么病症是死锁综合征还是死循环等其他病症本文我们一起来学习jstack命令~
jstack 的功能jstack用法线程状态等基础回顾实战案例1jstack 分析死锁实战案例2jstack 分析CPU 过高
jstack 的功能
jstack是JVM自带的Java堆栈跟踪工具它用于打印出给定的java进程ID、core file、远程调试服务的Java堆栈信息.
jstack prints Java stack traces of Java threads for a given Java process or core file or a remote debug server. jstack命令用于生成虚拟机当前时刻的线程快照。线程快照是当前虚拟机内每一条线程正在执行的方法堆栈的集合生成线程快照的主要目的是定位线程出现长时间停顿的原因 如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈就可以知道没有响应的线程到底在后台做什么事情或者等待什么资源。如果java程序崩溃生成core文件jstack工具可以用来获得core文件的java stack和native stack的信息从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外jstack工具还可以附属到正在运行的java程序中看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态jstack是非常有用的。 jstack用法
jstack 命令格式如下
jstack [ option ] pid jstack [ option ] executable core jstack [ option ] [server-id]remote-hostname-or-IP executable Java executable from which the core dump was produced.(可能是产生core dump的java可执行程序)core 将被打印信息的core dump文件remote-hostname-or-IP 远程debug服务的主机名或ipserver-id 唯一id,假如一台主机上多个远程debug服务 最常用的是
jstack [option] pid // 打印某个进程的堆栈信息
option参数说明如下 选项作用-F当正常输出的请求不被响应时强制输出线程堆栈-m如果调用到本地方法的话可以显示C/C的堆栈-l除堆栈外显示关于锁的附加信息在发生死锁时可以用jstack -l pid来观察锁持有情况
线程状态等基础回顾
线程状态简介
jstack用于生成线程快照的我们分析线程的情况需要复习一下线程状态吧拿小凳子坐好复习一下啦~ Java语言定义了6种线程池状态
New创建后尚未启动的线程处于这种状态不会出现在Dump中。RUNNABLE包括Running和Ready。线程开启start方法会进入该状态在虚拟机内执行的。Waiting无限的等待另一个线程的特定操作。Timed Waiting有时限的等待另一个线程的特定操作。阻塞Blocked在程序等待进入同步区域的时候线程将进入这种状态在等待监视器锁。结束Terminated已终止线程的线程状态线程已经结束执行。
Dump文件的线程状态一般其实就以下3种
RUNNABLE线程处于执行中BLOCKED线程被阻塞WAITING线程正在等待
Monitor 监视锁
因为Java程序一般都是多线程运行的Java多线程跟监视锁环环相扣所以我们分析线程状态时也需要回顾一下Monitor监视锁知识。
有关于线程同步关键字Synchronized与监视锁的爱恨情仇有兴趣的伙伴可以看一下我这篇文章 Synchronized解析——如果你愿意一层一层剥开我的心
Monitor的工作原理图如下 线程想要获取monitor,首先会进入Entry Set队列它是Waiting Thread线程状态是Waiting for monitor entry。当某个线程成功获取对象的monitor后,进入Owner区域它就是Active Thread。如果线程调用了wait()方法则会进入Wait Set队列它会释放monitor锁它也是Waiting Thread线程状态in Object.wait()如果其他线程调用 notify() / notifyAll() 会唤醒Wait Set中的某个线程该线程再次尝试获取monitor锁成功即进入Owner区域。
Dump 文件分析关注重点
runnable线程处于执行中deadlock死锁重点关注blocked线程被阻塞 重点关注Parked停止locked对象加锁waiting线程正在等待waiting to lock 等待上锁Object.wait()对象等待中waiting for monitor entry 等待获取监视器重点关注Waiting on condition等待资源重点关注最常见的情况是线程在等待网络的读写
实战案例1jstack 分析死锁问题
什么是死锁如何用jstack排查死锁
什么是死锁 死锁是指两个或两个以上的线程在执行过程中因争夺资源而造成的一种互相等待的现象若无外力作用它们都将无法进行下去。
如何用如何用jstack排查死锁问题
先来看一段会产生死锁的Java程序源码如下
/*** 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() {Overridepublic 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() {Overridepublic 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程序使用 jstack -l pid 查看线程堆栈信息分析堆栈信息
在终端中输入jsp查看当前运行的java程序 通过使用 jps 命令获取需要监控的进程的pid我们找到了23780 DeathLockTest 使用 jstack -l pid 查看线程堆栈信息 由上图可以清晰看到死锁信息
mythread-tianluo 等待这个锁 “0x00000000d61ae3a0”这个锁是由于mythread-jay线程持有。mythread-jay线程等待这个锁“0x00000000d61ae3d0”,这个锁是由mythread-tianluo 线程持有。
还原死锁真相 “mythread-tianluo线程堆栈信息分析如下
mythread-tianluo的线程处于等待waiting状态持有“0x00000000d61ae3d0”锁等待“0x00000000d61ae3a0”的锁
“mythread-jay线程堆栈信息分析如下
mythread-tianluo的线程处于等待waiting状态持有“0x00000000d61ae3a0”锁等待“0x00000000d61ae3d0”的锁 实战案例2jstack 分析CPU过高问题
来个导致CPU过高的demo程序一个死循环哈哈~
/*** 有个导致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过高步骤
toptop -Hp pidjstack pidjstack -l [PID] /tmp/log.txt分析堆栈信息 1.top
在服务器上我们可以通过top命令查看各个进程的cpu使用情况它默认是按cpu使用率由高到低排序的 由上图中我们可以找出pid为21340的java进程它占用了最高的cpu资源凶手就是它哈哈 2. top -Hp pid
通过top -Hp 21340可以查看该进程下各个线程的cpu使用情况如下 可以发现pid为21350的线程CPU资源占用最高~嘻嘻小本本把它记下来接下来拿jstack给它拍片子~ 3. jstack pid
通过top命令定位到cpu占用率较高的线程之后接着使用jstack pid命令来查看当前java进程的堆栈状态jstack 21350后内容如下 4. jstack -l [PID] /tmp/log.txt
其实前3个步骤堆栈信息已经出来啦。但是一般在生成环境我们可以把这些堆栈信息打到一个文件里再回头仔细分析哦~
5. 分析堆栈信息
我们把占用cpu资源较高的线程pid本例子是21350将该pid转成16进制的值 在thread dump中每个线程都有一个nid我们找到对应的nid5366发现一直在跑24行 这个时候可以去检查代码是否有问题啦~ 当然也建议隔段时间再执行一次stack命令再一份获取thread dump毕竟两次拍片结果jstack对比更准确嘛~ 来源
Java程序员必备jstack命令解析 - 掘金 (juejin.cn)
参考
jvm 性能调优工具之 jstack如何使用jstack分析线程状态Java命令学习系列二——Jstack