龙空技术网

jstack定位CPU占用率高的线程代码

程序员杨叔 202

前言:

今天朋友们对“jstack定位g问题”大概比较讲究,朋友们都想要知道一些“jstack定位g问题”的相关知识。那么小编同时在网上网罗了一些有关“jstack定位g问题””的相关知识,希望朋友们能喜欢,小伙伴们一起来了解一下吧!

一、背景

性能测试过程中,如果我们发现应用服务器CPU使用率高(超过70%),接口TPS低的现象,此时常见的情况是由以下的原因造成:

复杂的算法导致CPU使用率高,比如加解密算法、序列化等操作;代码中存在死循环;大量的logback日志异步写日志消耗cpu;频繁的fullGC;

这个时候为了进一步定位具体是哪段代码导致CPU使用率高,我们就需要用到jstack命令。整体步骤是:定位CPU占用率高的进程》定位该进程下CPU占用率高的线程》查看该线程堆栈信息日志》定位具体是哪个java类的哪一行代码造成。

二、jstack定位实战演示

1、首先在我的linux虚拟机上先运行一个jmeter,持续长时间运行。

2、使用top命令,查看系统中进程CPU使用率,按一下大写的P键,让进程按照使用率从上往下排序显示:

可以看到PID为4724的java进程占用CPU使用率最多,其实这个进程就是我们jmeter的进程。

3、这个时候有两种做法:

第一种:继续查看进程下到底哪些线程占用CPU高:top -H -p 4724

可以看到PID为4733和4739的线程CPU使用率高。

如果是java应用程序,想获得更多的线程相关信息,需要将上面的进程Id转换成16进制的,因为在java堆栈里,存储线程的Id采用的是16进制,可以直接命令printf %x 4739,输出:1283

使用jstack命令打印指定线程的运行日志信息:jstack 4739 | grep -C10 1283 --color

4739是进程号,1283是线程的16进制ID,-C10是指显示关键字所在行和前后10行,–color是指带颜色显示关键字1283。

第二种:直接使用命令 jstack 4724 > 1.txt, 表示直接把进程4724下所有线程运行日志信息,存储到文件 1.txt中, 即我们常说的thread dump文件。

查看1.txt的内容:

三、关于线程的状态

一般定义一个线程,有6种状态:

NEW: 代表新建状态;RUNNABLE 运行状态,就绪(ready)和运行中(running)两种状态笼统的称为“运行”;BLOCKED 阻塞状态,线程阻塞于锁;WAITING 等待状态,进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断);TIMED_WAITING 超时等待状态,该状态不同于WAITING,它可以在指定的时间后自行返回;TERMINATED 终止状态,表示该线程已经执行完毕。

但是在线程堆栈日志dump文件中,堆栈中的状态和上面线程定义的状态会不太一样。

thread dump 文件下,有以下的线程状态,通常需要重点关注的状态已标粗,这些状态的线程通常是最耗cpu的线程,重点关注这些线程并定位代码:

死锁,Deadlock(死锁,重点关注)执行中,Runnable等待资源,Waiting on condition(等待资源,可能线程已经出现排队现象了,重点关注)等待获取监视器,Waiting on monitor entry(重点关注)暂停,Suspended对象等待中,Object.wait() 或 TIMED_WAITING阻塞,Blocked(重点关注,阻塞状态)停止,Parked

含义如下所示:

Deadlock:死锁线程,一般指多个线程调用间,进入相互资源占用,导致一直等待无法释放的情况。Runnable:一般指该线程正在执行状态中,该线程占用了资源,正在处理某个请求,有可能正在传递SQL到数据库执行,有可能在对某个文件操作,有可能进行数据类型等转换。Waiting on condition:等待资源,或等待某个条件的发生。如果堆栈信息明确是应用代码,则证明该线程正在等待资源。一般是大量读取某资源,且该资源采用了资源锁的情况下,线程进入等待状态,等待资源的读取。又或者,正在等待其他线程的执行等。如果发现有大量的线程都在处在Wait on condition,从线程stack看,正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。另外一种出现 Wait on condition的常见情况是该线程在 sleep,等待 sleep的时间到了时候,将被唤醒。Blocked:线程阻塞,是指当前线程执行过程中,所需要的资源长时间等待却一直未能获取到,被容器的线程管理器标识为阻塞状态,可以理解为等待资源超时的线程。Waiting for monitor entry:意味着线程在等待进入一个临界区。Monitor是Java中用以实现线程之间的互斥与协作的主要手段,它可以看成是对象或者 Class的锁。每一个对象都有,也仅有一个monitor。这种状态通常发生在线程在等待数据库连接池返回一个可用的连接。四、最后

当程序出现故障,往往一次 dump 的信息,还不足以确认问题。建议最好多生成几次 dump 信息,比如3次,如果每次 dump 都指向同一个线程代码,我们才确定问题的典型性。以上,就是如何使用jstack命令查看CPU使用率高的线程运行日志信息,定位到具体的代码行。

=================================

以上就是本次的全部内容,如果对你有帮助,欢迎关注我的微信公众号:程序员杨叔,各类文章都会第一时间在上面发布,持续分享全栈测试知识干货,你的支持就是作者更新最大的动力~

标签: #jstack定位g问题