【Java可执行命令】(二十一)线程快照生成工具 jstack:帮助开发人员分析和排查线程相关问题(死锁、死循环、线程阻塞...)

news2024/9/27 9:30:52

Java可执行命令之jstack

  • 1️⃣ 概念
  • 2️⃣ 优势和缺点
  • 3️⃣ 使用
      • 3.1 语法格式
      • 3.2 使用步骤及技巧
      • 3.3 使用案例
  • 4️⃣ 应用场景
  • 🌾 总结

在这里插入图片描述


1️⃣ 概念

jstack 命令是 Java Development Kit(JDK)中提供的一项诊断工具,用于生成Java虚拟机(JVM)的线程快照。它的主要设计目的是帮助开发人员分析和排查应用程序中的线程相关问题,如死锁、死循环、线程阻塞等。

线程快照是指在某个时间点上,记录下所有运行在JVM中的线程的状态信息,包括线程栈、线程ID、线程所属的进程ID等。通过线程快照,我们可以了解线程执行状态、调用堆栈、线程的持有锁、等待资源等详细信息。

jstack 命令工具有以下特征:

  • 生成文本文件:jstack 命令生成的线程快照以文本文件形式输出,方便存储和后续分析;
  • 多种输出格式:jstack 提供了多种输出格式,如16进制、16进制元数据等,以满足不同场景下的需求;
  • 线程状态信息:线程快照中包含了每个线程的状态信息,如WAITINGTIMED_WAITINGBLOCKED等;
  • 堆栈追踪:通过解析线程的栈帧(Stack Frame),可以查看线程执行的方法调用轨迹。这对于发现死锁或代码性能调优至关重要。

jstack的原理实际是通过Java虚拟机提供的ThreadMXBean 接口获取线程相关信息,并将获取到的信息打印到控制台或文本文件中。它会遍历JVM中的所有线程,然后获取线程堆栈信息和其他状态信息,最终输出线程快照。

2️⃣ 优势和缺点

优点:

  • jstack命令能够提供关键的线程信息,方便开发人员快速定位和诊断线程相关问题;
  • JDK自带的工具,无需额外配置,使用方便;
  • 命令执行速度较快,在诊断简单问题方面效果良好。

缺点:

  • jstack只提供静态的线程快照,不能实时监控和连续跟踪线程,在某些复杂场景下可能不够全面。

3️⃣ 使用

3.1 语法格式

jstack 命令的使用语法如下:

Usage:
    jstack [-l] <pid>
        (to connect to running process)(连接到正在运行的进程)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)(连接到挂起的进程)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)(连接到核心文件)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)(连接到远程调试服务器)

其中,[-l] -F[-m] 都是可选的一些命令参数选项,<pid> 是Java进程的进程ID。对于命令中可选参数汇总如下:

参数说明
-F以强制线程转储。当 jstack<pid>没有响应时使用(进程挂起)
-m打印java和本机框架(混合模式)
-l长清单,打印有关锁的其他信息
-h or -help打印帮助信息

需要注意以下几点:

  • 在使用jstack命令生成线程快照时,目标Java进程可能会暂停执行,影响应用程序的性能;
  • 对于生产环境的Java进程,建议在非高峰期或业务低谷时使用 jstack命令,以减少对正常业务流程的干扰;
  • 考虑保密性:线程快照可能包含敏感信息(如部分代码逻辑),请确保妥善处理线程快照文件以防止泄露。

3.2 使用步骤及技巧

  • 找到目标进程的 PID:可以通过jps命令来查看Java进程的进程ID;
  • 执行命令:在命令行中输入jstack <pid>,即可生成线程快照;
  • 分析线程信息:打开生成的线程快照文本文件,查看线程状态、堆栈追踪等信息;
  • 利用线程ID定位问题:根据线程ID可以在堆栈追踪中定位对应的代码和资源问题,帮助进行问题诊断。

对于大规模线程的应用程序,可以使用多次执行jstack <pid>并比较不同快照的结果,以检测潜在的线程问题。
同时也可以结合其他工具(如jvisualvm)使用,可以更全面地分析和调试线程相关问题。

3.3 使用案例

(1)通过jps命令来查看Java进程的进程ID;

c:\Users\xxx\IdeaProjects\untitled15\src\com\xiaoshan>jps
15216 TestDemo
166976 Launcher
172008 Jps
172716

(2)在命令行中输入jstack ,生成线程快照;

c:\Users\xxx\IdeaProjects\untitled15\src\com\xiaoshan>jstack 15216

执行结果:

2023-08-09 15:19:52
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.202-b08 mixed mode):

"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x00000000193c8800 nid=0x2a5d4 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #10 daemon prio=9 os_prio=2 tid=0x00000000193a8000 nid=0x28a78 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x000000001939e800 nid=0x2a108 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000001939e000 nid=0x29dd0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x0000000019399800 nid=0x25afc waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x00000000193a0000 nid=0x29528 runnable [0x000000001a9be000]
   java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
        - locked <0x00000000d6688070> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:161)
        at java.io.BufferedReader.readLine(BufferedReader.java:324)
        - locked <0x00000000d6688070> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:49)

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000019353000 nid=0x28dbc waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000000019300000 nid=0x2a1b8 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000017c23800 nid=0x2a5b8 in Object.wait() [0x000000001a64f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d6508ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
        - locked <0x00000000d6508ed0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00000000192e3000 nid=0x2a504 in Object.wait() [0x000000001a54f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d6506bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x00000000d6506bf8> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"main" #1 prio=5 os_prio=0 tid=0x0000000002a63000 nid=0x2a1bc runnable [0x00000000024be000]
   java.lang.Thread.State: RUNNABLE
        at java.io.FileInputStream.readBytes(Native Method)
        at java.io.FileInputStream.read(FileInputStream.java:255)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
        - locked <0x00000000d655a9c0> (a java.io.BufferedInputStream)
        at com.xiaoshan.test.TestDemo.main(TestDemo.java:38)

"VM Thread" os_prio=2 tid=0x0000000017c16800 nid=0x1414 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002a78800 nid=0x27c9c runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002a7a000 nid=0x296a0 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002a7b800 nid=0x2a498 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002a7d000 nid=0x2a304 runnable

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x0000000002a7f800 nid=0x470 runnable

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000000002a81800 nid=0x2794c runnable

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000000002a85000 nid=0x5450 runnable

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000000002a86000 nid=0x47bc runnable

"GC task thread#8 (ParallelGC)" os_prio=0 tid=0x0000000002a87000 nid=0x29ec0 runnable

"GC task thread#9 (ParallelGC)" os_prio=0 tid=0x0000000002a88800 nid=0x2a624 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x00000000193c9000 nid=0x29c78 waiting on condition

JNI global references: 12


此结果是Java虚拟机线程转储(Full thread dump)的输出。它提供了一个关于在Java程序中正在运行的所有线程的信息快照。以下是每个线程的解释:

  1. "Service Thread":服务线程,是用于执行后台任务的线程。
  2. "C1 CompilerThread3":即时编译器线程,负责编译Java字节码为本地代码,以提高执行效率。
  3. "C2 CompilerThread2":另一个即时编译器线程,也负责编译Java字节码为本地代码。
  4. "C2 CompilerThread1":即时编译器线程的另一个实例。
  5. "C2 CompilerThread0":即时编译器线程的另一个实例。
  6. "Monitor Ctrl-Break":监控Ctrl-Break事件的线程,可用于在IDE中终止程序执行。
  7. "Attach Listener":监听Java虚拟机附加事件的线程。
  8. "Signal Dispatcher":信号分发线程,用于处理操作系统发送的信号。
  9. "Finalizer":Finalizer线程,负责执行对象的finalize()方法(垃圾回收前的清理工作)。
  10. "Reference Handler":引用处理线程,用于处理Reference类型的对象。
  11. "main":主线程,程序的入口点。
  12. "VM Thread":虚拟机线程,执行必要的虚拟机任务。
  13. "GC task thread#0 (ParallelGC)""GC task thread#9 (ParallelGC)":并行垃圾回收(ParallelGC)线程。在此例中,有10个线程用于并行垃圾回收。
  14. "VM Periodic Task Thread":周期性任务线程,定期执行虚拟机内部的一些任务。

最后一行指示JNI全局引用的数量为12,这是Java Native Interface(JNI)使用的内存资源。

以"Service Thread"线程为例,详细解释一个线程的输出信息:

"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x00000000193c8800 nid=0x2a5d4 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
  • 线程名称:“Service Thread”;
  • 线程编号(Thread ID):0x00000000193c8800
  • Native ID(nid):0x2a5d4
  • 守护线程标识(daemon):守护线程(daemon),这意味着当所有非守护线程结束时,该线程会被自动终止;
  • 线程优先级(priority):9,具有10个等级的优先级范围(1为最低,10为最高);
  • 操作系统优先级(os_priority):0,表示该线程在操作系统中使用默认的优先级设置;
  • 线程特定标识符(tid):0x00000000193c8800
  • 线程状态(java.lang.Thread.State):RUNNABLE,表示该线程当前正在运行或准备运行。

总而言之,该输出提供了关于Java程序运行时各个线程的详细信息,包括线程名称、优先级、状态以及线程正在执行的代码位置(如果可获得)。

4️⃣ 应用场景

  • 线程死锁定位:通过观察线程快照中的锁信息,可以排查应用程序中的死锁问题;
  • 程序性能分析:通过分析线程状态和堆栈信息,可以发现耗时操作、线程阻塞等导致程序性能下降的原因;
  • 代码调优:通过观察方法调用轨迹,可以确定是否存在效率低下的代码段,进而进行优化。

🌾 总结

jstack 命令是Java开发人员调试和分析线程相关问题时常用的工具。它能够生成线程快照,提供有关线程状态和堆栈追踪的重要信息,帮助开发人员定位线程问题、代码性能问题以及资源争用问题。尽管其输出是静态的,不能实时监控线程状态,但是在处理简单线程问题时具有较高的效果。

了解jstack的使用方法、特征、优化技巧和注意事项,能够提升开发人员在排查线程问题方面的能力,进一步提升应用程序的性能和稳定性。

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

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

相关文章

震坤行工业超市旗下震坤行智能制造(苏州)有限公司开工奠基仪式圆满成功

震坤行工业超市旗下震坤行智能制造&#xff08;苏州&#xff09;有限公司开工奠基仪式圆满成功 2023年7月3日&#xff0c;震坤行工业超市于太仓港经济技术开发区举行了震坤行智能制造&#xff08;苏州&#xff09;有限公司项目奠基动工仪式。震坤行董事长兼CEO陈龙&#xff0c…

基于OFDM通信系统的低复杂度的资源分配算法matlab性能仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .......................................................................%子载波分配[~,po…

Grafana技术文档-概念-《十分钟扫盲》

Grafana官网链接 Grafana: The open observability platform | Grafana Labs 基本概念 Grafana是一个开源的度量分析和可视化套件&#xff0c;常用于对大量数据进行实时分析和可视化。以下是Grafana的基本概念&#xff1a; 数据源&#xff08;Data Source&#xff09;&#…

idea+gradle阅读spring5.2.9源码之源码构建报错解决方案

注意 1、先确保gradle版本和spring、jdk版本对应 本文:gradle:5.6.4/spring 5.2.9/jdk1.8&#xff08;gradle和jdk都要先安装好&#xff0c;gradle还要配置好本地资源文件路径&#xff09; 2、原来项目乱了的话&#xff0c;先重新导入下载的源码项目 3、进入源码所在根目录&…

【iOS】autoreleasepool

来说一下最近在了解的autoreleasepool吧&#xff0c;我们可能平时书写过许多脑残代码&#xff0c;其有很多的缺陷但是我们可能当时学的比较浅就也不太了解&#xff0c;就像下面这样的&#xff1a; for (int i 0; i < 1000000; i) {NSNumber *num [NSNumber numberWithInt…

【前端 | CSS】aligin-items与aligin-content的区别

align-items 描述 CSS align-items 属性将所有直接子节点上的 align-self 值设置为一个组。align-self 属性设置项目在其包含块中在交叉轴方向上的对齐方式 align-items是针对每一个子项起作用&#xff0c;它的基本单位是每一个子项&#xff0c;在所有情况下都有效果&…

【uniapp】原生子窗体subNvue的使用与踩坑

需求 最近接到个需求, 需要在video组件上弹出弹窗, 也就是覆盖video这个原生组件 未播放时, 弹窗可以覆盖, 但是当video播放时, 写的弹窗就覆盖不了了 因为video是原生组件, 层级非常高, 普通标签是覆盖不了的, map标签同理 覆盖原生组件, 官方给出解决办法一. 使用cover-view…

文件传输软件常见问题解决办法大全

文件传输软件是我们工作中不可缺少的一种工具&#xff0c;它可以帮助我们快速、安全、稳定地传输各种文件&#xff0c;如文档、图片、视频等。但是在使用文件传输软件的过程中&#xff0c;我们也可能会遇到一些问题&#xff0c;影响我们的工作效率和传输质量。那么&#xff0c;…

【陈老板赠书活动 - 10期】- 【Python之光:Python编程入门与实战】

陈老老老板&#x1f9b8; &#x1f468;‍&#x1f4bb;本文专栏&#xff1a;赠书活动专栏&#xff08;为大家争取的福利&#xff0c;免费送书&#xff09; &#x1f468;‍&#x1f4bb;本文简述&#xff1a;生活就像海洋,只有意志坚强的人,才能到达彼岸。讲一些我刚进公司的学…

【ARM Cache 系列文章 9 番外篇 -- ARMv9 系列 Core 介绍】

文章目录 ARMv9 系列CoreARM Cortex-A510 介绍ARM Cortex-A715ARM Cortex-A720 ARMv9 系列Core 2021年5月Arm公布了其最新3款CPU和3款GPU核心设计&#xff0c;三款新CPU分别是旗舰核心Cortex-X2、高性能核心Cortex-A710、高能效核心Cortex-A510 CPU&#xff0c;三款新GPU核心则…

【Linux】深入探索Linux信号

目录 写在前面的话 什么是信号 生活中的信号 Linux下的信号 Linux常见信号 Core核心转储 信号如何产生 键盘组合键 1.如何理解信号被进程保存 2.如何理解信号发送的本质 通过系统调用向进程发送信号 kill() 手动实现kill指令 raise() abort()[非系统调用…

Django ORM 框架中的表关系,你真的弄懂了吗?

Django ORM 框架中的表关系 为了说清楚问题&#xff0c;我们设计一个 crm 系统&#xff0c;包含五张表&#xff1a; 1.tb_student 学生表 2.tb_student_detail 学生详情表 3.tb_salesman 课程顾问表 4.tb_course 课程表 5.tb_entry 报名表 表关系和字段如下图&#xff1a…

String 类的运用

目录 1.字符串构造 2.String对象的比较 2.1比较是否引用同一个对象 2. 2boolean equals(Object anObject) 2.3int compareTo(String s) 方法: 按照字典序进行比较 2.4int compareToIgnoreCase(String str) 3.字符串查找 4.2大小写转换 4.3字符串转数组 4.4 格式化 5.字…

java 企业工程管理系统软件源码 自主研发 工程行业适用 em

​ 工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#…

好用的无线蓝牙耳机怎么选?七款真无线蓝牙耳机分享盘点

随着蓝牙技术的不断进步&#xff0c;近年来蓝牙耳机发展更是呈指数式上升阶段。蓝牙耳机凭借其携带便捷性以及摆脱线的缠绕而在外出必备数码产品中名列前茅&#xff0c;现如今在日常生活中随处可见的都有戴着蓝牙耳机的人&#xff0c;或是听歌、或是降噪、或是玩游戏等等&#…

分享实录 | 将 NGINX 打造成功能强大的 API 网关(上)

原文作者&#xff1a;易久平 原文链接&#xff1a;分享实录 | 将 NGINX 打造成功能强大的 API 网关&#xff08;上&#xff09; NGINX 唯一中文官方社区 &#xff0c;尽在 nginx.org.cn 大家好&#xff0c;很高兴加入此次 NGINX 深潜之旅。接下来我将给大家分享如何将 NGINX 打…

DP(状态机模型)

大盗阿福 阿福是一名经验丰富的大盗。趁着月黑风高&#xff0c;阿福打算今晚洗劫一条街上的店铺。 这条街上一共有 N 家店铺&#xff0c;每家店中都有一些现金。 阿福事先调查得知&#xff0c;只有当他同时洗劫了两家相邻的店铺时&#xff0c;街上的报警系统才会启动&#x…

Mac安装nvm教程及使用

nvm 是 node 版本管理器&#xff0c;也就是说一个 nvm 可以管理多个 node 版本&#xff08;包含 npm 与 npx&#xff09;&#xff0c;可以方便快捷的安装、切换 不同版本的 node。 1、直接通过brew安装 执行命令&#xff1a;brew install nvm PS&#xff1a; 如果没有安装br…

JDK 8 升级 JDK 17 全流程教学指南

JDK 8 升级 JDK 17 首先已有项目升级是会经历一个较长的调试和自测过程来保证允许和兼容没有问题。先说几个重要的点 遇到问题别放弃仔细阅读报错&#xff0c;精确到每个单词每一行&#xff0c;不是自己项目的代码也要点进去看看源码到底是为啥报错明确你项目引入的包&#x…

什么是碳中和认证申请气候友好证绿色标?

碳中和认证几乎所有卖家都适用&#xff0c;需要的资料比较简单&#xff0c;几乎所有的产品及所有的站点都可以做。 一、“碳中和”认证是什么&#xff1f; 碳中和认证是通过计算碳排放&#xff0c;减少碳排放&#xff0c;进而减少使地球变暖的温室气体的数量的一个认证。是亚…