【JAVA】java性能分析之线程DUMP分析

系统上线后,系统可能会出现一些迟钝、卡死现象,这个时候就需要我们对系统进行性能方面的优化。本文将大概介绍一下,性能问题的解决思路,以及一次应用系统操作缓慢的分析实操。

一、定位问题方向

首先,查看服务器CPU使用率,磁盘IO以及内存使用情况

1.占用内存几乎等于JVM参数中分配的内存大小,而且长时间处于这种状态的话,应该是程序中可能存在内存泄漏的问题,或者JVM参数设置不合适,从这方面入手。这方面要用到堆DUMP来分析。本文不展开介绍。

2.CPU使用率高或者磁盘IO一直很高的话,可能是有部分代码有问题,需要到线程DUMP文件中进行分析

3.如果这三样看起来都没有什么异常,需要去线程DUMP文件中进行查看,可能是线程死锁,线程阻塞,数据库查询执行缓慢等等问题

(偶尔慢的话,有可能恰好JVM在进行FULL GC,如果FULL GC很频繁,就需要在堆DUMP中进行分析,分析没什么问题后,要对JVM参数进行合理的设置,GC的搭配【1.8以后使用G1】。另外,FULL GC若是时间长,也有可能是分配的堆大小太大导致的)

二、制作线程DUMP

先找到系统进程PID
例如:我的java进程名字叫test,进程PID2316

1.使用jps查看Java进程ID(PID);
Linux下还可以使用ps命令。
jps -l | grep test
ps -ef | grep test

2.使用jstack制作线程Dump。jstack <进程ID> >> <输出文件>
jstack 2316 >> c:\thread.txt
(制作的时候,从点击页面操作开始到结束,执行该命令多次,不需要修改文件名,它是以追加的方式来写入文件,不会覆盖。这样有利于排除其他因素干扰,查看DUMP就可以对比着看)

三、分析线程DUMP工具
工欲善其事必先利其器
分析线程DUMP的工具有很多,我使用了一下三款:
1.TDA
TDA
2.IBM Thread and Monitor Dump Analyzer
IBM Thread and Monitor Dump Analyzer
3.YourKit
YourKit
先做一个粗略的对比
1.TDA
这是一个基础款,使用起来,Emmmm……原汁原味(一点都不方便)

2.IBM TDA
它把多次的线程DUMP排成了一个时序图,可以很方便的查看不同时段的线程DUMP,可以看到堆栈随时间而产生的变化。缺点:无法看到一个方法的执行时间,不能明确定位到具体的造成系统慢、卡顿的原因,只能靠猜。

3.YourKit
这个工具是收费的,还挺贵,他的仪表盘能够直观的看到CPU,磁盘,内存,死锁等等情况,也可以看到线程、方法、SQL执行时间,有很多个维度来查看,只需要按时间排序后,展开一个个方法就能定位到问题点,很方便。缺点:收费,贵。

关于这些工具的使用方法,网上应该挺多,在此不做赘述(后续看会不会写这些吧)。

四、分析线程DUMP的思路
1.线程DUMP内容
在这里插入图片描述
2.线程DUMP使用场景
系统无响应或响应慢,不知道系统状态时。
多线程并发相关的问题,如:死锁、阻塞等

3.线程DUMP的分析模式

分析的原则:
结合代码阅读的推理。需要线程Dump和源码的相互推导和印证。
造成Bug的根源往往不会在调用栈上直接体现,一定格外注意线程当前调用之前的所有调用。

可疑线程,三大入手点:

<1>进入区阻塞;
线程状态BLOCKED,线程动作wait on monitor entry,调用修饰waiting to lock总是一起出现。
表示在代码级别已经存在冲突的调用。必然有问题的代码,需要尽可能减少其发生。

<2>持续运行的IO;
IO操作是可以以RUNNABLE状态达成阻塞。例如:数据库死锁、网络读写。
格外注意对IO线程的真实状态的分析。
一般来说,被捕捉到RUNNABLE的IO调用,都是有问题的。

<3>非线程调度的休眠。

总结:
在这里插入图片描述

死锁问题分析的“三板斧”

<1>在最可能死锁的时间点上制作Dump。
<2>找出引起大量线程阻塞的线程。线程X锁住了对象A,大量其他线程在对象A上阻塞。
<3>分析导致该线程阻塞的原因。导致线程X阻塞的原因,数据库事务?内存事务?其他状态?
<4>阅读代码,遍历其它等待或阻塞的线程的调用线索。其他线程在当前调用前,已经完成的所有的调用,是否可能造成线程X的阻塞?

GC的干扰、Dump的比较
虚拟机执行Full GC时,会阻塞所有的用户线程。因此,即时获取到同步锁的线程也有可能被阻塞。这时可以制作多份线程Dump,使用工具的比较功能,分析系统的连续状态。

五、一次分析系统缓慢的实例

将DUMP文件导入IBM TDA 后,选定所有行,compare threads。可以看到下方窗口有线程的整体信息,各个线程状态的信息有多少
在这里插入图片描述
打开后的页面,左边是线程名称,中间是多份线程DUMP,类似一个时序图,右边是调用栈
在这里插入图片描述
选定用户线程,点击各个时间的DUMP文件,查看堆栈,进行分析
右边有一个dispatch方法,这是一个同步调用方法,在代码中查看,给一个系统发消息,同步调用,时间都耗在了等待返回上(12S)。貌似是一个废弃接口,而且这个业务没必要同步,把这里改成异步就好了。

性能分析深似海,只能一步一步来!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值