感觉写的非常不错

前言

如果有一天,你的Java程序长时间停顿,也许是它病了,需要用jstack拍个片子分析分析,才能诊断具体什么病症,是死锁综合征,还是死循环等其他病症,本文我们一起来学习jstack命令~

jstack 的功能

jstack用法

线程状态等基础回顾

实战案例1:jstack 分析死锁

实战案例2:jstack 分析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服务的主机名或ip

server-id 唯一id,假如一台主机上多个远程debug服务

最常用的是

jstack [option]   // 打印某个进程的堆栈信息

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,等待资源(重点关注),最常见的情况是线程在等待网络的读写

实战案例1:jstack 分析死锁问题

什么是死锁?

如何用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() {

@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程序

使用 jstack -l pid 查看线程堆栈信息

分析堆栈信息

在终端中输入jsp查看当前运行的java程序

通过使用 jps 命令获取需要监控的进程的pid,我们找到了23780DeathLockTest

使用 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”的锁

实战案例2:jstack 分析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过高步骤

top

2.top -Hp pid

3. jstack pid

4. jstack -l [PID] >/tmp/log.txt

5. 分析堆栈信息

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进程的堆栈状态,jstack21350后,内容如下:

4. jstack -l [PID] >/tmp/log.txt

其实,前3个步骤,堆栈信息已经出来啦。但是一般在生成环境,我们可以把这些堆栈信息打到一个文件里,再回头仔细分析哦~

5. 分析堆栈信息

我们把占用cpu资源较高的线程pid(本例子是21350),将该pid转成16进制的值

在thread dump中,每个线程都有一个nid,我们找到对应的nid(5366),发现一直在跑(24行)

这个时候,可以去检查代码是否有问题啦~ 当然,也建议隔段时间再执行一次stack命令,再一份获取thread dump,毕竟两次拍片结果(jstack)对比,更准确嘛~

参考与感谢

jvm 性能调优工具之 jstack (https://www.jianshu.com/p/025cb069cb69)

如何使用jstack分析线程状态 (https://www.jianshu.com/p/6690f7e92f27)

Java命令学习系列(二)—Jstack(http://www.hollischuang.com/archives/110)

java jstack 分析_jstack 分析一下java程序相关推荐

  1. java jstack使用_jstack命令的使用

    文章来源:https://blog.csdn.net/wufaliang003/article/details/80414267 jstack是java虚拟机自带的一种堆栈跟踪工具. jstack用于 ...

  2. java jstack使用_jstack命令详解

    jstack命令可以用来查看运行的Java进程下,多线程的运行情况,语句如"[root@admin ~]# jstack 43616 Full thread dump Java HotSpo ...

  3. java程序假死_分析一个常见的java多线程通信问题(假死现象)

    一件复杂的事,一个人如果不能做,两个人又做的不好,一群人就可能很好的解决了.对于线程来说也是,通过多个线程就能完成一个更复杂的功能,这就需要多个线程协作,协作就需要交流,但是交流总是会出问题的.在这篇 ...

  4. java jstack 分析工具_JVM分析工具——jstack实践

    JVM分析工具--jstack实践 一.不是万能的jstack 企业级的Java程序中,java程序出现性能低下甚至直接崩溃时,就不能像解决业务bug那样,从行为表现上来修复问题了.性能问题一般是jv ...

  5. Java黑皮书课后题第7章:7.4(分析成绩)编写一个程序,读入个数不确定的考试分数,并且判断有多少个分数是大于或等于平均分,多少个分数是低于平均分的。输入一个负数表示输入结束。假设最高分是100

    7.4(分析成绩)编写一个程序,读入个数不确定的考试分数,并且判断有多少个分数是大于或等于平均分,多少个分数是低于平均分的.输入一个负数表示输入结束.假设最高分是100 题目 题目描述 破题 代码 运 ...

  6. jstack: Java占用高CPU分析之- C2 Compiler Thread

    1. 现象 应用刚上线时发现Java进程占用了大量的CPU份额,但过了几分钟后会降下来(流量没变的情况下),因为已经做了负载均衡,于是拿一台实例重新部署代码上线来分析.具体分析步骤参考另外一篇文章&l ...

  7. java 自带thread分析工具_java自带的jvm分析工具

    这段时间觉得很有必要对java的内存分析工具进行熟悉,这样以后出现机器负载较高,或者反应很慢的时候,我就可以查找原因了.上网搜了搜,发现下面这些是比较常用的,然后我在机器上试试了,把结果也贴出来哈. ...

  8. jstat 内存泄漏_基于Java内存dump文件分析解决内存泄漏问题

    概述 本文介绍一次解决现场java内存泄漏问题的经过,希望能提供后续遇到类似情况的读者一点思路. 生产环境发现的问题问题 生产环境运维人员反馈,服务器(windows系统)卡死,相关的服务都运行异常, ...

  9. jstack命令案例分析:对wait的线程没有调用notify()导致程序无法停止

    对wait的线程没有调用notify()导致的结果就是程序无法停止. o.notify(); //必须,否则无法停止程序 public class T06_00_sync_wait_notify {p ...

最新文章

  1. Windows下Caffe的学习与应用(三)——使用OpenCV3调用自己训练好的Caffe模型进行图像分类
  2. id_Tech5_challenges--siggraph09
  3. android componentname activity,ComponentName的使用
  4. LoadRunner 8.1 学习笔记4
  5. spring启动执行_执行器的Spring启动和安全性事件
  6. Wince6.0编译错误经验总结
  7. “An exception has been raised that is likely due to a transient failure. Consider enabling transient
  8. 电脑遇到DNS服务器未响应的情况该怎么办
  9. golang超时控制
  10. 北通手柄连接电脑没反应_北通手柄连接电脑教程
  11. 拉卡拉考拉超收,关于它的全部信息!
  12. MySQL部署OGG
  13. 32java访问(http):国家气象局 免费接口
  14. 笔记本电脑终于可以待机了
  15. 载图工具snipaste
  16. (转载)有关推挽输出、开漏输出、复用开漏输出、复用推挽输出以及上拉输入、下拉输入、浮空输入、模拟输入区别...
  17. [python爬虫之路dya3]: requests库的基本使用
  18. 像素、灰度、RGB、分辨率
  19. uart转RS422
  20. 常用的设计模式(泡妞经典版)

热门文章

  1. SSRF漏洞的攻击与防御
  2. 行业凛冬,BAT程序员是如何应对中年危机的?
  3. 解决地质云网站无法打开的问题
  4. js判断客户端是pc端还是移动端
  5. 【计算机网络 24】TCP/IP数据包结构详解
  6. java 图片线条_如何在一个图中为不同的图形获得不同的彩色线条?
  7. 三菱PLC转盘机程序 此程序已经实际设备上批量应用
  8. tolower函数什么意思c语言,tolower ()在c语言中是什么意思
  9. RCMTM _百度百科
  10. 手把手教你用增强现实技术戴上Apple Watch!