jstack命令解析

前言

如果有一天,你的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] <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程序,源码如下:

/*** 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”的锁

 

实战案例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
  • top -Hp pid
  • jstack pid
  • jstack -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,我们找到对应的nid(5366),发现一直在跑(24行)

 

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

来源

  • Java程序员必备:jstack命令解析 - 掘金 (juejin.cn)

参考

  • jvm 性能调优工具之 jstack
  • 如何使用jstack分析线程状态
  • Java命令学习系列(二)——Jstack

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

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

相关文章

一、cadence PDK 自学笔记-心法

我这边ADS /Cadence PDK基本大部分都是自学完成的。 当然也非常感谢我的前同事周**的帮忙&#xff0c;教了我很多基础的。另外也感谢我现在同事&#xff0c;李**和程*的帮忙&#xff0c;学习了很多cad的视角。 其实对于自学写PDK的小伙伴&#xff0c;一般都要如何学习呢&…

深度学习入门笔记(六)线性回归模型

本节&#xff0c;我们用线性回归为例子&#xff0c;回顾一些基本概念 6.1 相关性 相关性的取值范围是-1 到 1&#xff0c;越接近 1 或者-1 代表越相关&#xff0c;越接近 0 则越不相关。相关系数大于 0 称为正相关&#xff0c;小于 0 称为负相关。 假如 A 与 B 正相关&#…

[UI5 常用控件] 05.FlexBox, VBox,HBox,HorizontalLayout,VerticalLayout

文章目录 前言1. FlexBox布局控件1.1 alignItems 对齐模式1.2 justifyContent 对齐模式1.3 Direction1.4 Sort1.5 Render Type1.6 嵌套使用1.7 组件等高显示 2. HBox,VBox3. HorizontalLayout&#xff0c;VerticalLayout 前言 本章节记录常用控件FlexBox,VBox,HBox,Horizontal…

快速理解复杂系统组成学习内容整合

目录 一、复杂系统组成 二、接入系统 (Access System) 三、应用系统 (Application System) 四、基础平台 (Foundation Platform) 五、中间件 (Abundant External Middleware) 六、支撑系统 (Supporting System) 参考文章 一、复杂系统组成 复杂系统是由多个相互关联、相…

React中的事件处理逻辑

在React中&#xff0c;事件处理逻辑是通过在组件上添加事件监听器来实现的。事件监听器是一个函数&#xff0c;它会在特定的事件发生时被调用。可以通过以下几个步骤来处理事件逻辑: 在组件类中定义事件处理函数。例如&#xff0c;可以在组件类中定义一个叫做handleClick的事件…

比瓴科技入围软件供应链安全赛道!为关键信息基础设施安全建设注入新动力

1月20日&#xff0c;中关村华安关键信息基础设施安全保护联盟会员大会暨关键信息基础设施安全保护论坛在北京成功举办&#xff0c;比瓴科技作为会员单位受邀出席。 本次论坛发布了《关键信息基础设施安全保护支撑能力白皮书&#xff08;2023&#xff09;》&#xff0c;比瓴科技…

蓝桥杯客观题练习笔记

1、蓝桥杯单片机开发板供电为几V&#xff1f; 5V DS18B20是单工通讯&#xff0c;还是半双工通讯&#xff1f;为什么&#xff1f; 将时钟线&#xff0c;数据线&#xff0c;控制线和电源线合并为一根线&#xff0c;只要符合单总线协议的器件都能以从机的身份挂接到单总线上与主…

【开源】SpringBoot框架开发大学计算机课程管理平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 实验课程档案模块2.2 实验资源模块2.3 学生实验模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 实验课程档案表3.2.2 实验资源表3.2.3 学生实验表 四、系统展示五、核心代码5.1 一键生成实验5.2 提交实验5.3 批阅实…

许昌路280号3号办公楼室内精装修项目

许昌路280号3号办公楼室内精装修项目 (招标编号:2024-上水管线-201) 项目所在地区:上海市 一、招标条件 本许昌路280号3号办公楼室内精装修项目已由项目审批/核准/备案机关批准&#xff0c;项目资金来源为国有资金0万元:私有资金0万元;境外资金0万元;自筹资金480万元;外国政府及…

获取真实 IP 地址(二):绕过 CDN(附链接)

一、DNS历史解析记录 DNS 历史解析记录指的是一个域名在过去的某个时间点上的DNS解析信息记录。这些记录包含了该域名过去使用的IP地址、MX记录&#xff08;邮件服务器&#xff09;、CNAME记录&#xff08;别名记录&#xff09;等 DNS 信息。DNS 历史记录对于网络管理员、安全研…

架构师为什么要写文档?又该如何写文档呢?

大家好&#xff0c;我是冰河~~ 最近有很多小伙伴&#xff0c;也不乏身边的一些同事问我&#xff1a;哎&#xff0c;架构师为什么要写这么多文档啊&#xff1f;有啥用呢&#xff1f;不能跟开发一样多写写代码吗&#xff1f;天天写文档&#xff0c;又感觉自己的文档写不好&#…

2023年12月CCF-GESP编程能力等级认证Python编程五级真题解析

Python等级认证GESP(1~6级)全部真题・点这里 一、单选题(共15题,共30分) 第1题 通讯卫星在通信网络系统中主要起到( )的作用。 A:信息过滤 B:信号中继 C:避免攻击 D:数据加密 答案:B 第2题 小杨想编写一个判断任意输入的整数N是否为素数的程序,下面哪个方法…

怪物联萌小游戏

欢迎来到程序小院 怪物联萌 玩法&#xff1a;将怪物连体&#xff0c;怪物只能直线上下左右移动&#xff0c;躲过障碍物&#xff0c;共16关卡&#xff0c; 不同关卡不同界面&#xff0c;遇到金币记得吃掉金币哦&#xff0c;会获得更高分数&#xff0c;快去闯关吧^^。开始游戏ht…

纯血鸿蒙来了,鸿蒙App开发该如何提速

“全世界做产品挣钱的公司很多&#xff0c;但有能力打造操作系统的公司没有几家&#xff0c;最后世界上的操作系统就只有三套&#xff1a;鸿蒙、iOS和安卓。” --- 360集团创始人、董事长周鸿祎 “HarmonyOS实现了AI框架、大模型、设计系统、编程框架、编程语言、编译器等全栈…

git的分支操作

目录 简介&#xff1a; 操作&#xff1a;查看 操作&#xff1a;创建 操作&#xff1a;切换​编辑 操作&#xff1a;本地分支推送到远程 操作&#xff1a;git merge [name]合并分支​编辑 简介&#xff1a; 在Git中&#xff0c;可以通过分支来管理和处理不同的版本和功能。分…

一文读懂C++的类和对象以及多态的原理

现实生活中&#xff0c;关于类和对象最好的例子是自然界的动物类&#xff0c;本文将以此为场景逐步引入C的概念&#xff0c;达到学习的目的。因为C这门语言本身有很多繁杂的内容&#xff0c;而网上的资源也是参差不齐&#xff0c;有的人见山谈山遇水聊水&#xff0c;有多人故弄…

已解决!AttributeError: ‘Sequential‘ object has no attribute ‘session‘ 问题

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通Golang》…

事件在状态流程图中的工作方式

什么是事件&#xff1f; 事件是一个Stateflow对象&#xff0c;它可以触发以下对象中一个动作&#xff1a; Simulink触发子系统 Simulink函数调用子系统 状态流程图 何时使用事件 当你想&#xff1a; 激活Simulink触发的子系统 激活Simulink函数调用子系统 在状态流程图…

MySQL进阶之触发器

触发器 触发器是与表有关的数据库对象&#xff0c;指在insert/update/delete之前(BEFORE)或之后(AFTER)&#xff0c;触 发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性 , 日志记录 , 数据校验等操作 。 使用别名OLD和NEW来引用…

EtherCAT转ModbusTCP网关

一、功能概述 1.1设备简介 本产品是EtherCAT和Modbus TCP网关&#xff0c;使用数据映射方式工作。 本产品在EtherCAT侧作为EtherCAT从站&#xff0c;接TwinCAT、CodeSYS、PLC等&#xff1b;在ModbusTCP侧做为ModbusTCP主站&#xff08;Client&#xff09;或从站&#xff08;…