实战-用top和jstack命令查找线上CPU消耗过高的线程

前言

在互联网行业中,高并发的业务为常态,作为一名Java高级工程师,线上问题的排查手段和技巧必须熟练,比如某电商团队的某个应用突然CPU超高,导致报警短信和邮件满天飞,如果让你来定位一个问题,并快速消除预警,你该怎么办?其中一点就是如何定位CPU消耗过高的线程,以及如何找到线程正在干的事情。帮助我们快速的定位问题和分析问题。

本文为日常工作中实战性较强的一个问题分析和定位技能。阅读完本文,你将拥有更高层次的问题分析和处理能力。

如何定位CPU高的线程

大体过程如下:

1、用top -H -p 命令找到CPU高的线程ID。
2、用jstack 命令打印jvm线程堆栈信息。
3、将第1步拿到的线程ID转换为16进制。(可以用命令 printf '%x\n' ID来输出16进制)
4、用转换后的线程ID在线程堆栈信息中查找匹配的nid线程。
5、到此已经找到线程,以及线程栈的详细信息。可以根据这些信息来判断应用当前正在干什么坏事了。

定位Java线程CPU消耗高的线程(top -H命令)

命令:pid为jvm进程号

top -H -p 

作用:列出指定进程下线程的信息,会按CPU的使用占比从大到小排列。

实战-用top和jstack命令查找线上CPU消耗过高的线程_第1张图片
top -H -p 得到的线程堆栈快照信息

上图中列分别代表的意思为:进程中的线程ID、用户名、线程优先级

列名 含义
PID 进程ID
USER linux用户名
PR 线程优先级
NI nice值。负值表示高优先级,正值表示低优先级
VIRT 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
RES 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
SHR 共享内存大小,单位kb
S 进程状态。
%CPU 上次更新到现在的CPU时间占用百分比
%MEM 进程使用的物理内存百分比
TIME+ 进程使用的CPU时间总计,格式:时:分:秒
COMMAND 命令名/命令行

上面的几个参数中,最关心的是PID、USER、%CPU信息。从上图中可以看到CPU占比最高的排在第1位,线程ID位14153(十六进制为:3749),这个线程就是我们想要的线程。

jstack命令

命令:pid为jvm进程号
作用:获取JVM线程堆栈快照

jstack 
实战-用top和jstack命令查找线上CPU消耗过高的线程_第2张图片
jstack得到的线程堆栈信息

在线程堆栈中提供如下的几个信息:

1、jvm内部的线程ID(tid), 操作系统上对应的线程ID(nid)
2、线程锁的状态,以及线程栈的轨迹信息。

如上图,线程JStack-Test对应的操作系统上的线程ID为0x3749

nid=0x3749

拿到这个ID,是不是有点高兴?有没有发现这个ID就是上一步中用top命令得到的ID?

有了线程堆栈信息,就能够根据线程栈轨迹、线程的状态来判断是否有死锁,线程执行的代码是什么代码。从而在这些信息的基础上进一步帮助我们分析系统的瓶颈、线程死锁、CPU资源消耗等情况。

对于线程堆栈的分析,将另起一篇文章来讲解。
敬请期待!!!

你可能感兴趣的:(实战-用top和jstack命令查找线上CPU消耗过高的线程)