JVM假死问题如何定位?

一、问题描述

最近接手了一个系统,线上有个定时循环执行的Java服务端程序,采用Spring+Quartz每五分钟计算一次。计算采用多线程执行,所有线程执行完成则当次任务执行完成,并记录计算结果的时间。在程序运行过程中,发现JOB会出现卡死的情况。


二、问题分析

1、查看运行job服务的进程是否正常

计算任务没有正常执行,首先查看tomcat的进程是否正常;
使用ps、top命令可以很容易查看到进程运行情况、以及每个进程中线程的运行情况;
通过查询结果发现当前进程正常,而计算线程卡死了,此时猜测可能因为线程产生了死锁,那么接下来就要分析下进程中所有线程的状态。

2、使用ps或jps命令找到进程的PID

 命令:ps -ef | grep tomcat

3、通过jstack命令dump线程堆栈信息

 命令: jstack -l  10115 >> dumpFile

4、查看线程的堆栈信息快照

下载步骤3中dump的快照文件到本地,部分线程堆栈信息如下:
JVM假死问题如何定位?_第1张图片
通过查看dump的快照并未发现有dead locked,排除了死锁的可能性。 多次dump线程快照,发现上面截图的线程一直处于RUNNABLE状态,分析打印出的信息发现处于I/O等待状态,通过线程堆栈信息可以定位到代码如下:
在这里插入图片描述
查看代码发现此处是通过httpClient调用第三方接口,使用的是httpClient4.1.3版本。经过分析得出如下结论:由于开发的同学在使用httpClient的时候没有设置超时时间,当网络或第三方服务出现问题没有response时,会一直等待,导致当前线程一直处于RUNNABLE的状态。
解决办法:设置httpClient的超时时间,重新上线,问题解决!


三、总结

  1. 由于线上tomcat启动时也没有配置JMX,因此无法使用jvisualvm图形化工具远程分析服务中进程情况;
  2. 个人认为在无图形化界面支持的情况,jstack工具是定位线上JAVA服务线程问题的神器。使用jstack可以dump出进程中所有线程(包括JVM自身的线程和用户线程)的堆栈信息、运行状态;
  3. jstack一次dump出的快照可能不足矣发现问题,通常多次dump快照文件进行分析;
  4. HttpClient4.X 版本使用时需要设置默认超时时间。HttpClient官方的示例也没提到要设置TimeOut,以至于很多同学在使用的时候也没有设置超时时间,这也是比较坑爹的地方。
  5. 以上问题定位步骤还可以应用于定位服务请求无响应的分析。以上问题定位步骤还可以应用于定位服务请求无响应的分析。

PS:希望对遇到此类问题的同学有帮助!

你可能感兴趣的:(JVM,httpClient,JVM假死,jstack,JVM性能优化)