原来jdk自带了这么好玩的工具 > 使用 jstack定位死循环

本文介绍了如何使用jstack工具来定位Java应用中的死循环和CPU高占用问题。通过理解jstack的作用、使用方法及其参数选项,结合实战案例在Linux和Windows系统中找出CPU占用最高的线程,分析线程堆栈信息,从而快速定位问题。文章还提及了jstack的补充手段,如在Java代码中直接打印堆栈。
摘要由CSDN通过智能技术生成

什么是jstack

  • jstack的主要作用是查看或者导出java线程的堆栈信息(快照);用于堆栈跟踪,当我们使用jstack命令时,它会将指定进程内的所有线程中方法的调用栈打印出来。

线程快照是java虚拟机内每一个线程正在执行的方法堆栈的集合,生成线程快照的主要目的是用于定位线程出现问题的位置;常见的问题有

  • 响应时间长
  • 线程死锁
  • 死循环
    当线程停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道线程的执行过程中在后台做了哪些事,在等待哪些资源造成的卡顿。

使用方法

命令格式

jstack [options] <pid>

options 参数说明

jstack的option参数并不多,真正用到的也就三个,接下来我们一个个介绍一下

--F:当线程挂起(Suspended)时,使用jstack -l pid命令是不会打印堆栈信息的,使用-F则可以强制输出线程堆栈;但是会停止但
--l:打印的信息除了堆栈外,还会显示锁的附加信息;
--m:同时输出java和C/C++的堆栈信息;在java的系统类库里面,有很多方法都是native修饰的,这些native修饰的方法你在java层面是看不到源码的,因为这些方法都是C/C++实现的;

状态说明

在线程的堆栈中,需要特别留意以下几种状态:

  • Deadlock: 死锁(重点关注)
  • Waiting on condition: 等待资源(重点关注)
  • Waiting on monitor entry : 等待获取监视器(重点关注)
  • Blocked :阻塞(重点关注)
  • Runnable :执行中
  • Suspended : 暂停
  • Object.wait()或 TIME_WAITING :对象等待中
  • Parked : 停止

no option 参数

不带option参数的命令

jstack 12771

打印结果如下

# ......忽略其他堆栈信息我们只关注main线程的堆栈
"main" #1 prio=5 os_prio=31 tid=0x00007fee9101a000 nid=0x2903 runnable [0x00007000085aa000]
   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 <0x000000076ab1ead0> (a java.io.BufferedInputStream)
	at com.test.Test.main(Test.java:12)
# .......忽略其他堆栈信息我们只关注main线程的堆栈

第一行各个单词的解析,

  • “main”:线程名称 。
  • prio:线程优先级
  • tid:指Java Thread id。
  • nid:指native线程的id。。
  • [0x00007000085aa000]:线程栈起始地址。

-l打印锁的附加信息

这里我们使用2个窗口,分别使用以下2个命令来测试

# 第一个窗口执行
jstack -l 12771

# 第二个窗口中执行
jstack  12771

通过2个窗口对比可以看到,加了-l的命令多打印了锁的信息;

导出堆栈文件

一般情况下,如果程序出错了, 都不会直接在生产环境的服务器上找错误,这个时候就可以用到一个非常实用的功能,将堆栈快照导出来,然后copy到别的电脑上看,命令如下

jstack -l 2289 > jstackDump.txt

执行后,就可以看到文件已经导出来了

通过cat命令可以看到,里面的内容和我们在命令行输出的内容是一样的

实战一 、 找出cpu占用最高的线程(linux系统)

首先我们准备好一个死循环的线程,在线程内定一个while的死循环,并且给这个线程起个名字为:yexindogn,阿里巴巴的开发规范里面有一个规定,就是每个线程必须起一个名字,起名字就是为了 以后程序出问题的时候好找错误;

    public static void main(String[] args) throws InterruptedException {
        new Threa
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值