
排查Java应用CPU过高
问题描述
测试环境CPU突然升高,日志查询无异常,可以通过使用jvm的调试工具定位问题。
一个服务器可能有多个java服务。通过top命令可查看是哪个服务cpu使用率较高。
1 | top |
top命令的输出可以分为两个部分:前半部分是系统统计信息,后半部分是进程信息。
前半部分信息:
第一行:系统当前时间、系统运行时间、当前登录用户数。load average 表示系统的平均负载,即任务队列的平均长度,分别表示 1 分钟、5 分钟、15 分钟
第二行:进程统计信息,分别有正在运行的进程数、睡眠进程数、停止的进程数、僵尸进程数
第三行:CPU统计信息,us 表示用户空间CPU占用率、sy 表示内核空间CPU占用率、ni 表示用户进程空间改变过优先级的进程 CPU 的占用率、id 表示空闲 CPU 占用率、wa 表示在进程执行过程中等待 IO 所占的百分比、hi 表示硬件中断所占的百分比、si 表示软件终端所占的百分比
几个概念:
RES:resident memory usage 常驻内存
(1)进程当前使用的内存大小,但不包括swap out
(2)包含其他进程的共享
(3)如果申请100m的内存,实际使用10m,它只增长10m,与VIRT相反
(4)关于库占用内存的情况,它只统计加载的库文件所占内存大小
RES = CODE + DATA
VIRT:virtual memory usage
(1)进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据等
(2)假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m,而不是实际的使用量
VIRT = SWAP + RES
每个java服务中有很多线程在执行,先定位到哪个线程CPU使用率较高,可以有下面3种方式:
-
通过ps命令
1
ps H -eo pid,tid,%cpu --sort=%cpu |grep <PID>
-
通过top命令
1
top -H -p <PID>
-
通过ps命令
1
ps -mp <PID> -o THREAD,tid,time
通过上面的方式的任意一种,找到CPU使用率较高的线程TID后,执行下面的命令:
1 | printf "0x%x\n" <线程TID> |
目的:将线程TID转换为16进制,为后面查找 jstack 日志做准备;
1 | jstack pid |grep tid -A 50 |


