关于jstack检测线程的死锁、等待、cpu耗时
背景
最近在项目中碰到一个问题,tomcat怎么都起不来,但是没有报任何的错误,当时请教了师兄,师兄一下就解决的,咨询之后,依赖的外部服务挂掉了,解决方法就jstack,然后看阻塞在哪个线程。所以为了下次不要犯这个错误,这里记录一下
jstack
- jstack是jdk自带的线程堆栈分析工具,使用该命令可以查看或者导出线程的堆栈信息。
jstack -l :进程挂起,强制打印堆栈信息,一般情况不使用
jstack -F :打印java和native c/c++框架的所有栈信息,一般应用排查不使用
jstack -m :一般不用
示例
jps查看java进程
jstack查看指定进程的当前堆栈情况:jstack pid
将指定进程的当前堆栈情况记录到某个文件中
jstack -l pid > /root/jstack_info.txt
jstack 高cpu占用率排除
1:在几乎没什么调用的情况下,服务器的cpu居高不下,非常有可能某个线程出现了死循环。
提示 在业务量不大,cpu占用率过高,死循环之外,还有可能是内存泄漏,导致大量的fullGC
2:在运行了一段死循环代码之后,开始排除
javac xxx.java
开始排查
-
使用top指令,定位cpu占用较高的进程
-
使用top -H -p pid 查看指定进程下各线程的cpu使用情况
注:PID虽然名为进程控制符,但其用途不限于特指进程id。如上图中PID列指的就是线程的id。 -
使用printf “%x” xxx指令将7678转化为十六进制。
-
使用jstack pid指令,查看当前的堆栈信息;并根据上一步得到的16进制的线程id,找到肇事线程。
jstack 7636 | grep 1dfe --col -A20 -
第五步:分析肇事线程堆栈信息。
①线程名。
②线程优先级。
③一个地址(该地址是什么地址,存疑)。
④线程十六进制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