关于jstack检测线程的死锁、等待、cpu耗时

背景

最近在项目中碰到一个问题,tomcat怎么都起不来,但是没有报任何的错误,当时请教了师兄,师兄一下就解决的,咨询之后,依赖的外部服务挂掉了,解决方法就jstack,然后看阻塞在哪个线程。所以为了下次不要犯这个错误,这里记录一下

jstack

  • jstack是jdk自带的线程堆栈分析工具,使用该命令可以查看或者导出线程的堆栈信息。

jstack -l :进程挂起,强制打印堆栈信息,一般情况不使用
jstack -F :打印java和native c/c++框架的所有栈信息,一般应用排查不使用
jstack -m :一般不用

示例

jps查看java进程
关于jstack检测线程的死锁、等待、cpu耗时

jstack查看指定进程的当前堆栈情况:jstack pid
关于jstack检测线程的死锁、等待、cpu耗时
将指定进程的当前堆栈情况记录到某个文件中
jstack -l pid > /root/jstack_info.txt

关于jstack检测线程的死锁、等待、cpu耗时

jstack 高cpu占用率排除

1:在几乎没什么调用的情况下,服务器的cpu居高不下,非常有可能某个线程出现了死循环。

提示 在业务量不大,cpu占用率过高,死循环之外,还有可能是内存泄漏,导致大量的fullGC

2:在运行了一段死循环代码之后,开始排除
javac xxx.java
开始排查

  • 使用top指令,定位cpu占用较高的进程

  • 使用top -H -p pid 查看指定进程下各线程的cpu使用情况
    关于jstack检测线程的死锁、等待、cpu耗时
    注:PID虽然名为进程控制符,但其用途不限于特指进程id。如上图中PID列指的就是线程的id。

  • 使用printf “%x” xxx指令将7678转化为十六进制。
    关于jstack检测线程的死锁、等待、cpu耗时

  • 使用jstack pid指令,查看当前的堆栈信息;并根据上一步得到的16进制的线程id,找到肇事线程。
    jstack 7636 | grep 1dfe --col -A20

  • 第五步:分析肇事线程堆栈信息。
    关于jstack检测线程的死锁、等待、cpu耗时
    ①线程名。

②线程优先级。

③一个地址(该地址是什么地址,存疑)。

④线程十六进制id。

⑤线程状态。

⑥线程当前所处方法。

⑦该箭头表示线程的执行历程。

注:此时,我们已经定位到了问题代码的位置⑥,接下来查看程序相应位置的代码,解决死循环问题即可。

死锁的:使用jstack pid指令,查看指定进程的堆栈信息,观察并定位到死锁线程。

https://blog.****.net/justry_deng/article/details/90447410 这个文章很不错

如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。

jstack Dump 日志文件中的线程状态

1:dump 文件里,值得关注的线程状态有

死锁 Deadlock (重点关注死锁线程,一般指多个线程调用间,进入相互资源占用,导致一直等待无法释放的情况。

执行中,Runnable

等待资源 Waiting on condition(重点关注该状态出现在线程等待某个条件的发生。具体是什么原因,可以结合 stacktrace来分析

等待获取监视器 Waiting on monitor entry(重点关注Monitor是 Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个 monitor。

暂停,Suspended

对象等待中,Object.wait() 或 TIMED_WAITING

阻塞 Blocked(重点关注 线程阻塞,是指当前线程执行过程中,所需要的资源长时间等待却一直未能获取到,被容器的线程管理器标识为阻塞状态,可以理解为等待资源超时的线程。

停止,Parked