jstack 命令解读
jstack
命令是JDK
工具之一,使用该命令可以打印正在运行中 Java
进程的栈信息。
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)
Options:-F 强制打印线程栈信息,在jstack <pid>命令没有响应的时候添加该选项可以实现强制打印-m (mix)混合模式,可以打印 Java 栈和本地方法栈-l (long listing)长列表模式. 额外打印关于锁的信息
jstack
用法
首先使用 jps
命令查看需要打印线程栈的java
进程号。
D:\Desktop>jps
17984 Launcher
9348 DeathLock
我们这里链接到 9348
这个进程号上,使用下面命令:
D:\Desktop>jstack 9348
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.281-b09 mixed mode):"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000018da5881000 nid=0x34c8 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLE"mythread2" #12 prio=5 os_prio=0 tid=0x0000018dc2547000 nid=0x2580 waiting on condition [0x000000468cdff000]java.lang.Thread.State: WAITING (parking)at sun.misc.Unsafe.park(Native Method)- parking to wait for <0x000000076b8dbf28> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)at java.util.concurrent.locks.LockSupport.park(Unknown Source)at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(Unknown Source)at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Unknown Source)at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(Unknown Source)at java.util.concurrent.locks.ReentrantLock.lock(Unknown Source)at DeathLock.lambda$deathLock$1(DeathLock.java:24)at DeathLock$$Lambda$2/1044036744.run(Unknown Source)at java.lang.Thread.run(Unknown Source)
可以看到控制台打印出了线程的信息以及线程对应的堆栈信息。下面我们对打印结果进行逐行分析:
java.lang.Thread.State: RUNNABLE
线程状态
首先需要分析的便是线程状态,在 Java
中线程会分别对应着不同的线程状态,从创建线程的 NEW
到销毁时的TERMINATED
状态。在java.lang.Thread.State
类中都有定义,想要分析源码的话可以打开该类进行查看。线程的状态有助于帮我们更好的分析线程的运行过程,下面贴一张图来描述线程之间状态的转换。
private static boolean exit = false;
// 在 new 一个线程对象后,该线程的状态为 NEW 状态
Thread thread1 = new Thread(()->{while(!exit){// 在执行线程中代码时,线程的状态为 RUNNABLE 状态System.out.println("current time is "+new Date())// 在执行睡眠代码时,线程会进入 TIMED_WAITTING 状态,并让出 CPU ,等待时间唤醒TimeUnit.SECONDS.sleep(1);}
});
// 在 start 之后,该线程的状态会进入 RUNNABLE 状态,并且等待系统调度后运行
thread1.start();
通过上述线程状态转移图可以帮助我们分析当前线程所处的状态以及他们运行逻辑。
我们通过 jstack
查看线程栈信息时通常看到的最多的是RUNNABLE
,BLOCKED
,WAITING
和TIMED_WAITING
这几种状态,我们一般看不到线程的NEW
和TERMINATED
状态,是因为在代码的运行过程中这两种状态只占很小一部分,我们捕捉到这两种状态前这两种状态已经一闪而过了。
"mythread2" #12
分析
以线程名称开头,所有线程都会在第一行打印一些当前线程的运行信息。
"main" #1 prio=5 os_prio=0 tid=0x0000000002e7e800 nid=0x2a1c in Object.wait() [0x0000000002f7f000]java.lang.Thread.State: WAITING (on object monitor)
其中开头是线程名称,后面的为线程信息:
#1
表示当前线程ID,从 main
线程开始,JVM
根据线程创建的顺序为线程编号。
prio
是priority
优先级的缩写,表名了当前线程的优先级,取值范围为[1-10],默认为 5。在虚拟机进行线程调度的时候会参考该优先级为线程分配计算资源,这个数值越低越有优先获取到计算资源,一般不设置直接使用默认的优先级。
os_prio
为线程对应系统的优先级。
nid
本地线程编号NativeID
的缩写,对应JVM 虚拟机中线程映射在操作系统中的线程编号。我们可以使用 top 查看进程对应的线程情况进行相关映射。
nid
的作用及其使用方式
如上面的描述nid
表示的是线程对应的系统本地的线程编号
线程锁解读
当一个线程占有一个锁的时候,线程堆栈会打印一个-locked<0x22bffb60>
// 示例代码
public class Main6 {private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) {final Thread task1 = new Thread(new Task());final Thread task2 = new Thread(new Task());task1.start();task2.start();}private static class Task implements Runnable {@Overridepublic void run() {lock.lock();int i = 0;while (true) {i++;}}}
}
当一个线程正在等在其他线程释放该锁,线程堆栈会打印一个-waiting to lock<0x22bffb60>
当一个线程占有一个锁,但又执行在该锁的wait上,线程堆栈中首先打印blocked
,然后打印-waiting on <0x22c03c60>
// 示例代码
public class Main7 {private static Object lock1 = new Object();private static Object lock2 = new Object();public static void main(String[] args) {final Thread task1 = new Thread(() -> {synchronized (lock1) {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lock2) {int i = 0;while (true) {i++;}}}});final Thread task2 = new Thread(() -> {synchronized (lock2) {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lock1) {int i = 0;while (true) {i++;}}}});task1.start();task2.start();}
}
使用 jstack
,top -Hp
获取目标线程的CPU使用情况
通过 jstack
可以打印出当前进程的线程栈信息,但是我们无法获取到这些线栈的 CPU 占用情况,此时,我们可以使用另外一个bash命令 top
去排查高 CPU 占用的线程。
首先使用 jps
命令获取目标 java 进程号:
[ghimi@node01 ~]$ jps
19332 Main7
然后使用 top -Hp <pid>
查看该进程下对应线程的CPU 使用情况:
这里如果我们想查看 PID
为19343
且线程名称为Thread-1
的堆栈信息的话(很明显这是我们创建的线程)。
首先我们需要将该线程好打印成 16进制的,可以使用电脑中自带的计算器,或者使用命令都可以:
使用计算器计算线程的16进制:
使用命令行获取16进制:
[ghimi@node01 ~]$ printf "%x\n" 19343
4b8f
接下来使用 jstack <pid>
查看线程堆栈信息:
#
jstack 19332 | grep -10 4b8f
由此我们可以看到目标线程的线程堆栈信息了。
使用 top -Hp <pid>
查看目标进程下各个线程的 CPU 使用情况
通过top -Hp <pid>
可以查看该进程下各个线程的CPU使用情况。
使用 pstree
查看进程树
通过命令 pstree
可以获取到系统当前运行过程中的进程树,像下面这样:
# -p 选项表示显示详细的进程识别码
pstree -p
使用 ps -Lf <pid>
查看进程详细信息
使用 ps -Lf <pid>
可以查看目标进程及其线程的信息。
jvm 监控工具Liberica Mission Control
参考资料
java线程状态和状态切换
jstack
jvm工具-jstack使用
jstack - 检测死锁、等待、CPU耗时
JVM线程模型详解
jstack日志线程分析
JVM 调优之 jstack 找出最耗cpu的线程
如何使用jstack分析线程状态
jstack 命令解读相关推荐
- jstack命令:教你如何排查多线程问题
转载自 jstack命令:教你如何排查多线程问题 这是之前的一个死锁案例: 一个多线程死锁案例,如何避免及解决死锁问题? 如程序中发生这样的死锁问题该如何排查呢?我们可以使用java自带的jstack ...
- jstack命令使用
概述 jstack可用于导出java运用程序的线程堆栈.其基本使用语法为: jstack [-l] pid -l 选项用于打印锁的额外信息. 使用演示样例 以下这段代码执行之后会出现死锁现象(由于线程 ...
- jstack命令分析
在线程中,有一些JVM内部的后台线程,来执行譬如垃圾回收,或则低内存的检测等等任务,这些线程往往在JVM初始化的时候就存在,比如如下例子: "Low Memory Detector" ...
- java命令_Java程序员,不得不会的JDK jstack命令工具
作者:Jay_huaxiao 链接:https://juejin.im/post/5ead8067e51d454da36cf182 如果有一天,你的Java程序长时间停顿,也许是它病了,需要用jsta ...
- jstack 命令使用经验总结和线程性能诊断脚本
编辑:业余草 来源:https://www.xttblog.com/?p=4946 分享一下,jstack 命令使用经验总结 jstack 在命令使用上十分简洁, 然而其输出的内容却十分丰富, 信息量 ...
- jstack命令 详解
1.介绍 jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息,如果是在64位机器上,需要指定选项"-J-d64",Windows的js ...
- jstack 命令的使用和问题排查分析思路
jstack 命令 什么是jstack jstack命令 jstack实战操作 什么是jstack jstack是用于生成java虚拟机当前时刻的线程快照.线程快照是当前java虚拟机内存每一条线程正 ...
- java 命令 线程栈_JVM调试常用命令——jstack命令与Java线程栈(1)
1 jstack 命令 jstack命令的主要作用是打印指定Java进程中每一个线程的工作状态,以及每个线程栈当前的方法执行顺序等详细情况.为什么jstack命令不和jmap.jinfo.jstat等 ...
- jstack命令(Java Stack Trace)
JDK内置工具使用 一.javah命令(C Header and Stub File Generator) 二.jps命令(Java Virtual Machine Process Status To ...
最新文章
- android 长按缩放拖动_十年Android之路面试2000人,面试准备+内部泄露核心题(中高级)...
- 参与势力战是不可多得的zhajinhua2012
- idea导入java项目步骤,idea与eclipse项目相互导入的过程(图文教程)
- keras 多输出问题
- Eclipse上安装maven插件时出错
- java中Assert使用
- js获取php多维数组,vue.js,多维数组_vuejs2.0 多维数组操作?,vue.js,多维数组 - phpStudy...
- xmind各版本区别_XMind各版本功能对比1.PDF
- SpringMVC中实现文件上传
- via浏览器原始css,简约却不简单—via浏览器
- 2021年电工(初级)考试内容及电工(初级)考试资料
- 网络中出现的问题、原因以及解决措施总结
- 学点负面情绪的抗争能力
- [设计模式]行为模式-模板方法(C++描述)
- 【备忘】hive 调优
- 电商类-仿美团页面demo
- JAVA设计模式总结之23种设计模式(重点!!!)
- 山寨版的《KingdomRush(皇城突袭)》
- 有哪些可以用于语文作文中的高级词汇?
- 三十二楼层选几层最好_32楼层的选择几层最好 住楼房几层最好风水