乐趣区

关于java:记录一次使用jstack和jstat分析线程问题实践

在测试环境进行测试时, 发现某个服务响应有一点点慢,于是 ssh 到对应环境,查看了一下 cpu 占用状况:

在应用
top 指令之后 看到的后果是这样的

正如咱们所晓得的 tomcat cpu 负载高 通常是:
1、代码问题:死循环、大量并发线程计算量大
2、full-gc : 有大对象产生、对象援用无奈开释
于是试图应用 jstack 命令剖析问题
首先应用

jstack -l 119236 | grep 'java.lang.Thread.State' | wc -l

统计了一下线程数

能够看到一共有 679 个线程

而后又别离统计了
RUNNABLE 线程数

jstack -l 119236 | grep 'java.lang.Thread.State: RUNNABLE' | wc -l

WAITING 的线程数

jstack -l 119236 | grep 'java.lang.Thread.State: WAITING' | wc -l

TIMED_WAITING 的线程数

jstack -l 119236 | grep 'java.lang.Thread.State: TIMED_WAITING'  | wc -l

BLOCKED 的线程数

jstack -l 119236 | grep 'java.lang.Thread.State:BLOCKED'  | wc -l

以及 死锁 (deadlock) 的线程数

jstack -l 119236 | grep 'Java-level deadlock'  | wc -l

能够看到, 一顿操作下来
咱们晓得了目前这个过程中 一共有 679 个线程 其中有
79 个线程处于 RUNNABLE( 线程运行中或 I / O 期待状态 )
347 个线程处于线程在 WAITING ( 有限期待唤醒的状态 )
66 个线程在 TIMED_WAITING ( 期待唤醒,但设置了时限的状态 )
0 个线程处于 BLOCKED 状态 ( 期待一个 monitor lock 的状态 )
没有发现死锁

既然没有死锁 那咱们看看导致是哪些线程导致了占用高呢?
接下来咱们应用指令 查看过程 119236 中 占用最高的线程
top -Hp 119236

咱们发现 这个 122318 占用十分高 达到了 45%, 于是咱们进一步将该线程的 pid 转为 16 进制输入
printf "%x\n" 122318

随后应用

jstack 119236 |grep 1ddce -A 30
看到占用最高的线程的具体信息

发现只是 redission 的线程, 作为一个分布式缓存锁, 该线程 cpu 占用高属于失常状况

随后咱们应用
jstat -gcutil 119236
查看该 java 过程的 gc 状况


能够看到在屡次间断的查问中 YGC(Minor GC) 的次数十分多, 然而理论耗费的工夫还是比拟正当的。

如果各项参数设置正当,零碎没有超时日志呈现,GC 频率不高,GC 耗时不高,那么没有必要进行 GC 优化;如果 GC 工夫超过 1〜3 秒,或者频繁 G C , 则必须优化。如果满足上面的指标,则个别不须要进行 GC:
■ Minor GC 执行工夫不到 50ms;
■ Minor GC 执行不频繁,约 10 秒一次;
■ Full GC 执行工夫不到 1s;

所以本次理论从线程剖析和 gc 剖析的角度来看,服务并无异样, 或者我该去看看接口, 溜了溜了

退出移动版