Java程序:jstack

news2024/11/27 21:03:35

前言

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

  • jstack 的功能

  • jstack用法

  • 线程状态等基础回顾

  • 实战案例1:jstack 分析死锁

  • 实战案例2:jstack 分析CPU 过高

jstack 的功能

jstack是JVM自带的Java堆栈跟踪工具,它用于打印出给定的java进程ID、core file、远程调试服务的Java堆栈信息.

 
  1. jstack prints Java stack traces of Java threads for a given Java process or

  2. 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 命令格式如下

 
  1. jstack [ option ] pid

  2. jstack [ option ] executable core

  3. 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服务

最常用的是

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

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

  • 什么是死锁?

  • 如何用jstack排查死锁?

什么是死锁?

死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法进行下去。

如何用如何用jstack排查死锁问题

先来看一段会产生死锁的Java程序,源码如下:

 
  1. /**

  2. * Java 死锁demo

  3. */

  4. public class DeathLockTest {

  5. private static Lock lock1 = new ReentrantLock();

  6. private static Lock lock2 = new ReentrantLock();

  7. public static void deathLock() {

  8. Thread t1 = new Thread() {

  9. @Override

  10. public void run() {

  11. try {

  12. lock1.lock();

  13. System.out.println(Thread.currentThread().getName() + " get the lock1");

  14. Thread.sleep(1000);

  15. lock2.lock();

  16. System.out.println(Thread.currentThread().getName() + " get the lock2");

  17. } catch (InterruptedException e) {

  18. e.printStackTrace();

  19. }

  20. }

  21. };

  22. Thread t2 = new Thread() {

  23. @Override

  24. public void run() {

  25. try {

  26. lock2.lock();

  27. System.out.println(Thread.currentThread().getName() + " get the lock2");

  28. Thread.sleep(1000);

  29. lock1.lock();

  30. System.out.println(Thread.currentThread().getName() + " get the lock1");

  31. } catch (InterruptedException e) {

  32. e.printStackTrace();

  33. }

  34. }

  35. };

  36. //设置线程名字,方便分析堆栈信息

  37. t1.setName("mythread-jay");

  38. t2.setName("mythread-tianluo");

  39. t1.start();

  40. t2.start();

  41. }

  42. public static void main(String[] args) {

  43. deathLock();

  44. }

  45. }

运行结果:

显然,线程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程序,一个死循环,哈哈~

 
  1. /**

  2. * 有个导致CPU过高程序的demo,死循环

  3. */

  4. public class JstackCase {

  5. private static ExecutorService executorService = Executors.newFixedThreadPool(5);

  6. public static void main(String[] args) {

  7. Task task1 = new Task();

  8. Task task2 = new Task();

  9. executorService.execute(task1);

  10. executorService.execute(task2);

  11. }

  12. public static Object lock = new Object();

  13. static class Task implements Runnable{

  14. public void run() {

  15. synchronized (lock){

  16. long sum = 0L;

  17. while (true){

  18. sum += 1;

  19. }

  20. }

  21. }

  22. }

  23. }

jstack 分析CPU过高步骤

     2.top -Hp pid

     3. jstack pid

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

     5. 分析堆栈信息

    1. top

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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/143019.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阳康后的第一篇博客,先来几道恶心二进制编程题

目录 一、统计二进制中1的个数 二、打印整数二进制的奇数位和偶数位 三、两个整数二进制位不同个数 一、统计二进制中1的个数 这是一道牛客网OJ题&#xff0c;感兴趣的话可以先做一遍再看解析哦 -> 牛客网的OJ链接 注意&#xff1a;上面的牛客网是接口型&#xff0c;不需…

Vagrant管理已存在的虚拟机

起因 某天打开VirtualBox后&#xff0c;发现之前创建的虚拟机都没了&#xff0c;后将虚拟机从本地磁盘又重新导入&#xff0c;但是发现使用 vagrant up 会创建新的虚拟机&#xff0c;而我要用vagrant管理已存在的虚拟机&#xff0c;就是 vagrant up的时候&#xff0c;我需要启动…

MySQL数据库:常用数据类型

一、整形和浮点型 数据类型大小说明对应C类型bit(n)n指定比特位数&#xff0c;默认1位比特位数&#xff0c;n范围1-64&#xff1b;存储数值范围2-2^n-1char[]tinyint1字节signed charsmallint2字节short intint4字节intbigint8字节long long intfloat(m,d)4字节单精度&#xf…

【前端】CSS基础

一、CSS基础 1.1CSS的介绍 CSS&#xff1a;层叠样式表&#xff08;Cascading style sheets&#xff09; CSS作用是什么&#xff1f;&#xff1f; 1.2CSS语法规则 写在哪里&#xff1f; CSS是style标签中&#xff0c;style标签一般写在head标签里面&#xff0c;title标签下…

真的强,又一个开源项目,杀疯了

最近&#xff0c;AI大模型连续火爆出圈&#xff0c;人工智能生成模型&#xff08;AIGC&#xff09;的热度尚未褪去&#xff0c;聊天机器人ChatGPT便引发全网热议&#xff0c;两周吸引百万用户。还有卷趴一半程序员的AlphaCode&#xff0c;生成全新蛋白质的ESM2等&#xff0c;不…

TypeScript,终于在实际项目中用到了泛型。

终于在实际项目中用到了泛型 里程碑式的纪录&#xff0c;终于不是anyScript了&#xff0c;代码写完只有一个any 应用 项目中组件化了这么一个东西 功能描述&#xff1a; 传进去一个数组&#xff0c;有个名&#xff0c;有个key&#xff0c;渲染成上图的div样式点击之后&#…

Triple 协议支持 Java 异常回传的设计与实现

作者&#xff1a;陈景明 背景 在一些业务场景&#xff0c;往往需要自定义异常来满足特定的业务&#xff0c;主流用法是在catch里抛出异常&#xff0c;例如&#xff1a; public void deal() {try{//doSomething ...} catch(IGreeterException e) {...throw e;} }或者通过…

Python面向对象(九)

python学习之旅(九) &#x1f44d;查看更多可以关注查看首页或点击下方专栏目录 一.什么是面向对象 万物皆对象 现实世界的事物都有属性和行为,可在程序中抽离为类来描述现实世界的事物属性和行为。 使用类充当程序内现实事物的“设计图纸”&#xff0c;基于图纸(类)生产实体…

10. 正则表达式匹配

题目链接&#xff1a;https://leetcode.cn/problems/regular-expression-matching/从暴力递归到动态规划&#xff0c;对于状态转移方程不容易推导出来的可以先从递归进行尝试各种策略&#xff0c;最后再从暴力递归转为动态规划&#xff0c;这种尝试方式容易求解dp初始值以及dp更…

数据结构-考研难点代码突破 (图关键路径完全解析(流程+代码) - C++代码)

考研在关键路径上的考察以流程为主 文章目录1. AOE网2. 关键路径问题解决流程C代码1. AOE网 首先区分AOV网&#xff1a; AOV网∶若用DAG 图&#xff08;有向无环图&#xff09;表示一个工程&#xff0c;其顶点表示活动&#xff0c;用有向边<Vi&#xff0c;Vj>表示活动 V…

【ESP32+freeRTOS学习笔记-(五)队列Queue】

目录1、什么是队列Queue2、队列的多任务特性2.1 多任务的访问&#xff1a;2.2 队列读取阻塞&#xff1a;2.3 写队列阻塞&#xff1a;2.4 阻塞于多个队列&#xff1a;3、队列的使用3.1 创建队列--The xQueueCreate() API3.2 写入队列3.3 从队列中接收数据3.4 删除队列4、队列集4…

ReactDOM.render在react源码中执行之后发生了什么?

ReactDOM.render 通常是如下图使用&#xff0c;在提供的 container 里渲染一个 React 元素&#xff0c;并返回对该组件的引用&#xff08;或者针对无状态组件返回 null&#xff09;。本文主要是将ReactDOM.render的执行流程在后续文章中会对创建更新的细节进行分析&#xff0c…

MATLAB-plot3/ezplot3三维绘图

&#xff08;1&#xff09; plot3是三维绘图的基本函数&#xff0c;调用格式如下。1、plot3( X,Y,Z):绘制简单的三维曲线&#xff0c;当X、Y、Z是长度相同的向量时&#xff0c;plot3命令将绘制以向量X、Y、Z为(x, y,z)坐标值的三维曲线;当X、Y、Z是mn矩阵时,plot3命令将绘制m条…

Android 虚拟分区详解(四) 编译开关

Android Virtual A/B 系统简称 VAB,我将其称为虚拟分区。 本系列文章基于 Android R(11) 进行分析,如果没有特别说明,均基于代码版本 android-11.0.0_r46 请已经购买《Android 虚拟分区》专栏的朋友加我 wx 进 "虚拟分区专栏 VIP 答疑"群,作为本专栏文章的附加服…

(6)元对象系统与信号与槽机制

1. 元对象系统 元对象系统是一个基于标准C的扩展&#xff0c;为Qt提供了信号与槽机制、实时类型信息、动态属性系统。 什么是元对象 在计算机科学中&#xff0c;元对象是这样一个东西&#xff1a;它可以操纵、创建、描述、或执行其他对象。元对象描述的对象称为基对象。元对象可…

记一次搭建备库,使用连接串主库无法连接到备库

主库使用连接串连接备库失败 SQL> conn sys/oracleorcldg as sysdba ERROR: ORA-12528: TNS:listener: all appropriate instances are blocking new connections 备库已经建立了静态监听 # listener.ora Network Configuration File: /u01/app/oracle/product/11.2.0/db_1/…

安全寒假第一堂课

一、状态码 200 – 服务器成功返回网页 404 – 请求的网页不存在 503 – 服务器超时 1xx&#xff08;临时响应&#xff09; 表示临时响应并需要请求者继续执行操作的状态码。 100&#xff08;继续&#xff09; 请求者应当继续提出请求。服务器返回此代码表示已收到请求的第一…

OpenCV实战(5)——图像运算详解

OpenCV实战&#xff08;5&#xff09;——图像运算详解0. 前言1. 图像基本运算2. 重载图像运算符2.1 加法运算符重载2.2 分割图像通道2.3 完整代码3. 图像重映射3.1 OpenCV 重映射函数3.2 完整代码小结系列链接0. 前言 图像可以以不同的方式进行组合&#xff0c;因为它们是正则…

XGBoost论文阅读

XGBoost: A Scalable Tree Boosting System 目录 XGBoost: A Scalable Tree Boosting System 1.摘要 2.方法 2.1 正则化学习目标 2.2 梯度提升树 2.3 收缩率和列采样 2.4分裂点查找算法 1.摘要 提出了一种新的稀疏性感知算法&#xff0c;用于稀疏数据和加权全图草图&a…

Python教程:什么是三级模式和二级映像?

美国国家标准学会(American National Standards Institute,ANSI)所属的标准计划与需求委员会&#xff08;Standards Planning and Requirements Committee,SPARC)在1971年公布的研究报告中提出了ANSI-SPARC体系结构&#xff0c;即三级模式结构&#xff08;或称为三层体系结构&a…