基于jstack的一次问题调查

一个长期运行的Web应用突然服务不可用,所有请求无法到达。通过jstack工具发现大量线程处于IN_NATIVE状态,最终定位到未设置超时的socket调用导致线程阻塞。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

jstack 

http://www.open-open.com/lib/view/open1456744049953.html 
http://wenku.baidu.com/link?url=XGRAXwZGpPIyvYzcs0fqOGazbnKWWy6tsuDk5XhPUmVI4Y9jOT5TiYf6JVq0sPGafvMJmZFs1dNDlNtovldedF5xwr9ViMvv6WdRSaTGkn_

    (案例:转)公司的一个web应用项目运行了很长一段时间,达半年之久,前段时间突然出现了服务不可用的情况,所有的请求都不可达,服务彻底挂了。查看tomcat进程还在,cpu使用率低,一时没找着问题,重启了服务。过了两天,又出现了这种情况, 开始排查最近更新上线的代码,但是也没有发现可疑之处。 
    
     开始怀疑JVM内存不够用了,通过jmap/jstat查看后,也没有发现存在JVM内存不够用,或者GC太频繁或者是FGC耗时太久的情况。 
    
     接着下来用jstack -F pid 把所有的线程信息dump下来,发现了很多“Thread 2341: IN_NATIVE”的线程,而且都来自同一个类;定位到该类,里面用了socket去跟第三方接口做交互,而socket没有设置SoTimeout时间,这样的话,socket将永久地等待,直到inputStream有数据; socket.setSoTimeout(3000)之后,报出了很多Read  timed out 的异常信息,很明显就是第三方接口出问题了。 
     
    所以出现故障的原因就是:一个http请求过来,tomcat接收到请求,分配一个worker Thread处理它,处理该请求的代码用到了前面提到的类,该worker Thread将永久处于socket.read()方法的wait状态或者说是IN_NATIVE状态;当时间一长,所有的worker thread都被占用,都处于socket.read()方法的wait状态后,tomcat没有worker thread处理任何的http请求了,故而应用会彻底挂掉;
### 使用 jstack 工具分析和解决 Java 应用程序中的 OOM 问题 #### 理解 jstack 的作用 `jstack` 是 JDK 自带的一种线程 dump 分析工具,它可以生成 Java 进程中所有线程的堆栈信息。通过这些信息,开发者能够深入了解当前进程中各个线程的状态、锁持有情况以及其他重要细节[^4]。 #### 获取目标进程 ID (PID) 要使用 `jstack` 对特定 Java 应用进行分析,首先需要知道该应用对应的 PID 。可以通过如下命令找到它: ```bash jps -lvm ``` 这条指令不仅返回基本的 PIDs ,还会附加更多有用选项比如 main class name 或 arguments passed during startup etc.[^2] #### 执行 jstack 命令 一旦获得了正确的 PID 后就可以运行下面这样的语句来捕获所需的 stack trace : ```bash jstack <pid> > threaddump.txt ``` 这里我们将结果重定向到了文件 "threaddump.txt" 中保存起来方便稍后的审查过程[^3]. #### 解读 Thread Dump 文件寻找线索 打开之前创建好的文本档, 寻找任何可疑之处例如死循环或者是长时间占用CPU资源却不释放它们的对象们等等... 特别注意那些标记为 'BLOCKED' 状态下的线程因为这意味着他们正等待着其他资源变得可用才能继续前进. 另外也要留意是否存在大量重复创建却未销毁干净的实例(如连接池管理不当)[^1]. 如果发现问题来源于第三方库内部实现缺陷的话可能就需要联系供应商寻求补丁更新版本了. 最后记得定期监测应用程序的表现确保修复措施生效并且没有引入新的瓶颈. ```bash # 示例脚本自动获取 pid 并导出 thread dump #!/bin/sh JAVA_PID=$(pgrep -f your.application.main.class.name) if [ ! -z "$JAVA_PID" ]; then echo "Found Java process with PID $JAVA_PID" jstack $JAVA_PID > /tmp/thread_dump_$JAVA_PID_$(date +%Y%m%d%H%M%S).log else echo "No matching Java processes found." fi ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值