目录

一、jstack:打印JVM中线程快照

二、jstack检测死锁

三、jstack观察线程状态

四、jstack观察线程同步问题


一、jstack:打印JVM中线程快照

jstack(JVM Stack Trace):用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。线程快照就是当前虚拟机内指定进程的每一条线程正在执行的方法堆栈的集合。

生成线程快照的作用:可用于定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。这些都是导致线程长时间停顿的常见原因。当线程出现停顿时,就可以用jstack显示各个线程调用的堆栈情况。

官方帮助文档:jstack

在thread dump中,要留意下面几种状态:

  • 死锁,Deadlock(重点关注)
  • 等待资源,Waiting on condition(重点关注)
  • 等待获取监视器,Waiting on monitor entry(重点关注)
  • 阻塞,Blocked(重点关注)
  • 执行中,Runnable
  • 暂停,Suspended
  • 对象等待中,Object.wait() 或 TIMED_WAITING
  • 停止,Parked
C:\Users\WSH>jstack -h
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)Options:-F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)-m  to print both java and native frames (mixed mode)-l  long listing. Prints additional information about locks-h or -help to print this help message

option参数说明如下:

option参数

作用

-F

当正常输出的请求不被响应时,强制输出线程堆栈

-l

除堆栈外,显示关于锁的附加信息

-m

如果调用本地方法的话,可以显示C/C++的堆栈

二、jstack检测死锁

public class DeadLockTest {public static void main(String[] args) {Object obj1 = new Object();Object obj2 = new Object();new Thread(() -> {synchronized (obj1) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}synchronized (obj2) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}}, "Thread-A").start();new Thread(() -> {synchronized (obj2) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}synchronized (obj1) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}}, "Thread-B").start();}
}

启动程序,使用jstack生成当前时刻的线程快照:

C:\Users\WSH>jstack 15684
2021-09-08 22:13:19
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.291-b10 mixed mode):"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x00000218f42c1000 nid=0x9d0 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Thread-B" #13 prio=5 os_prio=0 tid=0x00000218924e1000 nid=0x4864 waiting for monitor entry [0x000000f830aff000]java.lang.Thread.State: BLOCKED (on object monitor)at com.wsh.DeadLockTest.lambda$main$1(DeadLockTest.java:33)- waiting to lock <0x000000076e22cdd8> (a java.lang.Object)- locked <0x000000076e22cde8> (a java.lang.Object)at com.wsh.DeadLockTest$$Lambda$2/935044096.run(Unknown Source)at java.lang.Thread.run(Thread.java:748)"Thread-A" #12 prio=5 os_prio=0 tid=0x00000218924dc800 nid=0x3d78 waiting for monitor entry [0x000000f8309ff000]java.lang.Thread.State: BLOCKED (on object monitor)at com.wsh.DeadLockTest.lambda$main$0(DeadLockTest.java:16)- waiting to lock <0x000000076e22cde8> (a java.lang.Object)- locked <0x000000076e22cdd8> (a java.lang.Object)at com.wsh.DeadLockTest$$Lambda$1/1066516207.run(Unknown Source)at java.lang.Thread.run(Thread.java:748)"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x00000218921a8000 nid=0x2fac runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C1 CompilerThread3" #10 daemon prio=9 os_prio=2 tid=0x00000218920ec000 nid=0x2d74 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C2 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x00000218920e9000 nid=0x48a4 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x00000218920e2800 nid=0x380c waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x00000218920df800 nid=0x4404 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x00000218920de000 nid=0x1f4c runnable [0x000000f8302fe000]java.lang.Thread.State: RUNNABLEat 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 <0x000000076e2c5730> (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 <0x000000076e2c5730> (a java.io.InputStreamReader)at java.io.BufferedReader.readLine(BufferedReader.java:389)at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000002188fbd3000 nid=0x2f54 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000002188fbd2800 nid=0x2c0c runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000002188fba4800 nid=0x2d78 in Object.wait() [0x000000f82ffff000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000076e008ee0> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)- locked <0x000000076e008ee0> (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=0x000002188fb9d800 nid=0x1fd8 in Object.wait() [0x000000f82feff000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000076e006c00> (a java.lang.ref.Reference$Lock)at java.lang.Object.wait(Object.java:502)at java.lang.ref.Reference.tryHandlePending(Reference.java:191)- locked <0x000000076e006c00> (a java.lang.ref.Reference$Lock)at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)"VM Thread" os_prio=2 tid=0x000002188fb73800 nid=0x41fc runnable"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000218f42d8000 nid=0x3ffc runnable"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00000218f42d9000 nid=0x1bdc runnable"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00000218f42da800 nid=0x132c runnable"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00000218f42db800 nid=0x45f4 runnable"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00000218f42df000 nid=0x3fd8 runnable"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00000218f42e0000 nid=0x1820 runnable"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00000218f42e3000 nid=0x1430 runnable"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00000218f42e4000 nid=0x3008 runnable"GC task thread#8 (ParallelGC)" os_prio=0 tid=0x00000218f42e5000 nid=0x2750 runnable"GC task thread#9 (ParallelGC)" os_prio=0 tid=0x00000218f42e5800 nid=0x36f8 runnable"VM Periodic Task Thread" os_prio=2 tid=0x0000021892284800 nid=0x3964 waiting on conditionJNI global references: 316Found one Java-level deadlock:
=============================
"Thread-B":waiting to lock monitor 0x000002188fba3fb8 (object 0x000000076e22cdd8, a java.lang.Object),which is held by "Thread-A"
"Thread-A":waiting to lock monitor 0x000002188fba1728 (object 0x000000076e22cde8, a java.lang.Object),which is held by "Thread-B"Java stack information for the threads listed above:
===================================================
"Thread-B":at com.wsh.DeadLockTest.lambda$main$1(DeadLockTest.java:33)- waiting to lock <0x000000076e22cdd8> (a java.lang.Object)- locked <0x000000076e22cde8> (a java.lang.Object)at com.wsh.DeadLockTest$$Lambda$2/935044096.run(Unknown Source)at java.lang.Thread.run(Thread.java:748)
"Thread-A":at com.wsh.DeadLockTest.lambda$main$0(DeadLockTest.java:16)- waiting to lock <0x000000076e22cde8> (a java.lang.Object)- locked <0x000000076e22cdd8> (a java.lang.Object)at com.wsh.DeadLockTest$$Lambda$1/1066516207.run(Unknown Source)at java.lang.Thread.run(Thread.java:748)Found 1 deadlock.

可以看到,Thread-A和Thread-B两个线程都处于BLOCKED阻塞状态,相互在等待对方的监视器锁,所以通过jstack能够帮我们自动检测出死锁的存在。

三、jstack观察线程状态

public class ThreadSleepTest {public static void main(String[] args) {try {Thread.sleep(1000 * 60 * 10);} catch (InterruptedException e) {e.printStackTrace();}}
}

通过jstack命令可以看到,main主线程当前处于TIMED_WAITING超时等待状态,注意并不是无限制的WAITING。

四、jstack观察线程同步问题

public class ThreadSyncTest {public static void main(String[] args) {Number number = new Number();Thread t1 = new Thread(number);t1.setName("线程1");Thread t2 = new Thread(number);t2.setName("线程2");t1.start();t2.start();}
}class Number implements Runnable {private int number = 1;@Overridepublic void run() {while (true) {synchronized (this) {if (number <= 100) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ":" + number);number++;} else {break;}}}}
}
C:\Users\WSH>jstack 12864
2021-09-08 22:25:22
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.291-b10 mixed mode):"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x00000222072f3000 nid=0x114 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"线程2" #13 prio=5 os_prio=0 tid=0x0000022224f0e800 nid=0x4768 waiting for monitor entry [0x000000f7a9bff000]java.lang.Thread.State: BLOCKED (on object monitor)at com.wsh.Number.run(ThreadSyncTest.java:22)- waiting to lock <0x000000076e22e918> (a com.wsh.Number)at java.lang.Thread.run(Thread.java:748)"线程1" #12 prio=5 os_prio=0 tid=0x0000022224f0d800 nid=0x1db4 waiting on condition [0x000000f7a9aff000]java.lang.Thread.State: TIMED_WAITING (sleeping)at java.lang.Thread.sleep(Native Method)at com.wsh.Number.run(ThreadSyncTest.java:24)- locked <0x000000076e22e918> (a com.wsh.Number)at java.lang.Thread.run(Thread.java:748)"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x0000022224e9a000 nid=0xd40 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C1 CompilerThread3" #10 daemon prio=9 os_prio=2 tid=0x0000022224ddc000 nid=0x2f7c waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C2 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x0000022224dd9000 nid=0x3820 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x0000022224dd5000 nid=0x2df4 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x0000022224dd1000 nid=0x4e20 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x0000022224d81000 nid=0x44d4 runnable [0x000000f7a93fe000]java.lang.Thread.State: RUNNABLEat 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 <0x000000076e2c5838> (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 <0x000000076e2c5838> (a java.io.InputStreamReader)at java.io.BufferedReader.readLine(BufferedReader.java:389)at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000022222776800 nid=0x33e0 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x0000022222760000 nid=0x10c4 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLE"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000002222274b000 nid=0x24a0 in Object.wait() [0x000000f7a90fe000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000076e008ee0> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)- locked <0x000000076e008ee0> (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=0x0000022222743000 nid=0x3380 in Object.wait() [0x000000f7a8fff000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x000000076e006c00> (a java.lang.ref.Reference$Lock)at java.lang.Object.wait(Object.java:502)at java.lang.ref.Reference.tryHandlePending(Reference.java:191)- locked <0x000000076e006c00> (a java.lang.ref.Reference$Lock)at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)"VM Thread" os_prio=2 tid=0x0000022222718800 nid=0x1f40 runnable"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x000002220730a000 nid=0x3434 runnable"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x000002220730b000 nid=0x3b18 runnable"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x000002220730c800 nid=0x44cc runnable"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000002220730d800 nid=0xd4c runnable"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x000002220730f800 nid=0x129c runnable"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000022207310800 nid=0x4590 runnable"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000022207313800 nid=0x634 runnable"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000022207314800 nid=0x3f50 runnable"GC task thread#8 (ParallelGC)" os_prio=0 tid=0x0000022207316800 nid=0x403c runnable"GC task thread#9 (ParallelGC)" os_prio=0 tid=0x0000022207317800 nid=0x2804 runnable"VM Periodic Task Thread" os_prio=2 tid=0x0000022224f06800 nid=0xf10 waiting on conditionJNI global references: 12

如上当前时刻的线程快照中,我们可以看到,线程1处于TIMED_WAITING超时等待状态,而线程2处于BLOCKED阻塞状态,因为加了synchronized同步锁,所以两个线程中必定有一个线程需要等待获取锁。

JVM监控及诊断工具命令行篇之jstack相关推荐

  1. JVM 学习笔记二十五、JVM监控及诊断工具-命令行篇

    二十五.JVM监控及诊断工具-命令行篇 1.概述 性能诊断是软件工程师在日常工作中经常面对和解决的问题,在用户体验至上的今天,解决好应用软件的性能问题能带来非常大的收益. Java作为最流行的编程语言 ...

  2. 14、JVM监控及诊断工具-命令行篇

    文章目录 第1章.概述 1.简单命令行工具 第2章.jps:查看正在运行的Java进程 1.基本情况 2.基本语法 [1]options参数 [2]hostid参数 第3章.jstat:查看JVM统计 ...

  3. JVM监控及诊断工具命令行篇之jps

    目录 一.概述 二.jps:查看正在运行的Java进程 一.概述 性能诊断是软件工程师在日常工作中需要经常面对和解决的问题,在用户体验至上的今天,解决好应用的性能问题能带来非常大的收益. Java 作 ...

  4. JVM监控及诊断工具-命令行篇一

    1 jps 基本概述 jps(java process status),用于查看正在运行的java虚拟机进程,会显示指定系统内所有的HotSpot虚拟机进程(查看虚拟机进程信息).这里说明一下,对于本 ...

  5. JVM学习笔记之-JVM性能监控-JVM监控及诊断工具-命令行方式

    性能优化的步骤 第1步(发现问题):性能监控 一种以非强行或者入侵方式收集或查看应用运营性能数据的活动. 监控通常是指一种在生产.质量评估或者开发环境下实施的带有预防或主动性的活动. 当应用相关干系人 ...

  6. 尚硅谷JVM下篇:性能监控与调优篇_02_JVM监控及诊断工具-命令行篇

    文章目录 1-概述 概述 简单命令行工具 2-jps:查看正在运行的Java进程 基本情况 基本语法: options参数 hostid参数 3-jstat:查看JVM统计信息 基本信息 基本语法 o ...

  7. JVM监控及诊断工具之GUI篇

    目录 工具概述 图形化综合诊断工具 jConsole 基本概述 启动 三种连接方式 Visual VM 基本概述 插件的安装 连接方式 基本使用 eclipse MAT 基本概述 获取堆dump文件 ...

  8. 性能监控与调优篇之【3. JVM 监控及诊断工具-GUI 篇】

    文章目录 3. JVM 监控及诊断工具-GUI 篇 3.1. 工具概述 3.2. JConsole 3.3. Visual VM 3.4. Eclipse MAT 3.5. JProfiler 3.6 ...

  9. JVM监控及诊断工具-GUI篇

    3.JVM监控及诊断工具-GUI篇 一.工具概述 使用上一章命令行工具或组合能帮您获取目标Java应用性能相关的基础信息,但它们存在下列局限: 1.无法获取方法级别的分析数据,如方法间的调用关系.各方 ...

  10. 20.JVM监控以及诊断工具-GUI篇

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 20. JVM监控及诊断工具-GUI篇 20.1. 工具概述 使用上一章命令行工具或组合能帮您获取目标Java应用性能相 ...

最新文章

  1. 多条记录取最近日期的一条_Excel VBA:基于员工打卡记录的考勤数据统计
  2. Spring5参考指南:Bean的创建
  3. 图论--欧拉回路(模板)
  4. 阿里技术专家麒烨:修炼测试基本功
  5. 【python零基础入门学习】Python入门,带你快速学习,Python 中文编码
  6. linux shell 解析文本文件,linux Shell 全解析
  7. 开心猫序列C语言,开心猫的读后感作文
  8. 使用C#调用非托管DLL函数
  9. [转载] Python集合set
  10. boost::bind 与 boost::function 的使用方法例子
  11. Day004 20210209-20210217
  12. RotateMenu简单地旋转菜单控件《IT蓝豹》
  13. php利用curl实现多进程下载文件类
  14. 山海经鸿蒙boss疲劳,《山海经》十大奇兽:吃了可缓解各种疑难杂症
  15. IDC中国大型企业SaaS云服务市场:金蝶位居第一
  16. 【摘记】彼得·林奇的成功投资
  17. Vue3.0 项目启动(打造企业级音乐App)
  18. 浙江大学2020计算机考研复试线,浙江大学2020考研复试分数线已公布
  19. python学习笔记十-文件操作
  20. 如何识别小米设备/MIUI系统或其他品牌手机

热门文章

  1. jsp引进的js 显示404_【梅园大讲堂微课堂】Get超级大招!上海人才引进云申报权威解读来了...
  2. 算法:Jump Game
  3. 计算机博弈军旗程序,军棋机器人UCT算法及计算机博弈行为研究
  4. android iptables清空,android中的iptables错误:iptables-save和iptables-restore无法正常工作...
  5. 钉钉微应用怎么进入_海目星激光张荣:激光焊接在锂电池生产应用中越来越多...
  6. 常用ajax调用方法,web前端之4种常用的Ajax请求方式
  7. 命令 所有的虚拟环境_Python虚拟环境安装与配置
  8. 估计理论(7):应用BLUE的两个例子
  9. FaceBoundingBoxInInfraredSpace 得到的深度空间的数值为空
  10. 【bug解决】You should consider upgrading via the 'pip install --upgrade pip' command.