CPU飙升可能出现在以下几种场景中:
- 死循环:当程序中存在无限循环时,CPU会一直执行循环代码,导致CPU占用率飙升。
- 大量计算:当程序需要进行大量的计算操作时,会导致CPU负载增加,从而使CPU占用率飙升。
- 死锁:当多个线程相互等待对方释放资源时,会导致死锁现象,此时CPU会一直处于忙碌状态,导致CPU占用率飙升。
- 高并发请求:当系统面临大量并发请求时,CPU需要同时处理多个请求,导致CPU占用率飙升。
- 病毒或恶意软件:当计算机感染病毒或运行恶意软件时,这些恶意程序可能会占用大量CPU资源,导致CPU占用率飙升
死循环案例:
@RestController
public class IndexController {
private static boolean process=true;
@RequestMapping("/user/cpu")
public String cpu() throws InterruptedException {
while(process){
add(3,4);
}
return "sucess";
}
void add(int a,int b){
int r = a + b;
}
}
1.top
在服务器上,我们可以通过top命令查看各个进程的cpu使用情况,它默认是按cpu使用率由高到低排序的
由上图中,我们可以找出pid为21340的java进程,它占用了最高的cpu资源
2. top -Hp pid
通过top -Hp 21340可以查看该进程下,各个线程的cpu使用情况,如下
3. 将线程pid转换为16进制
转换命令:$printf '%x\n' 线程pid
4. jstack 进度pid | grep -A 200 16进制线程ID
通过top命令定位到cpu占用率较高的线程之后,接着使用jstack pid命令来查看当前java进程的堆栈状态, jstack21350
后,内容如下:
在thread dump中,每个线程都有一个nid,我们找到对应的nid(5366),发现一直在跑(24行)
4. jstack -l [PID] >/tmp/log.txt
其实,前3个步骤,堆栈信息已经出来啦。但是一般在生成环境,我们可以把这些堆栈信息打到一个文件里,再回头仔细分析哦~
Dump 文件分析关注重点
runnable,线程处于执行中
deadlock,死锁(重点关注)
blocked,线程被阻塞 (重点关注)
Parked,停止
locked,对象加锁
waiting,线程正在等待
waiting to lock 等待上锁
Object.wait(),对象等待中
waiting for monitor entry 等待获取监视器(重点关注)
Waiting on condition,等待资源(重点关注),最常见的情况是线程在等待网络的读写
5.jmap -histo:live 进程id | more
使用jmap -histo:live 进程id|more , 会以表格的形式显示存活对象的信息,并按照所占用内存大小排序,对于实例数较多,占用内存大小较多的实例/类,相关的代码就要针对性的review了