linux java cpu爆满,服务器CPU又爆了?Linux快速排查Java程序占用CPU很高的方法

这个问题可以说是 Java 面试的高频面试题了,有很多面试官都喜欢问这个问题,问题可能是下面这样的。

线上一台服务器 CPU 使用率100% 了,如果你碰到这样的情况,如何排查并找到问题原因?

1.场景模拟

当我们真碰到这个问题的时候应该怎么排查呢?

先用一段程序创建几个线程,将其中一个线程设置成高 CPU 使用率的。

public static void main(String[] args) {

for (int i = 0; i < 10; i++) {

Thread thread = new Thread(() -> {

System.out.println(Thread.currentThread().getName());

try {

Thread.sleep(30 * 60 * 1000);

}catch (Exception e){

e.printStackTrace();

}

});

thread.setName("thread-" + i);

thread.start();

}

Thread highCpuThread = new Thread(() -> {

int i = 0;

while (true) {

i++;

}

});

highCpuThread.setName("HighCpu");

highCpuThread.start();

}

运行这段程序后,前面 10 个线程都处于休眠状态,只有最后一个线程会持续的占用 CPU 。

运行这段程序,然后就可以开始一些列的操作来发现问题原因了。

在linux上运行一段代码

2.排查步骤

第一步,使用 top 找到占用 CPU 最高的 Java 进程

在真实环境中,首先要确认是不是 Java 程序造成的,如果有系统监控工具,可能会直接在预警信息里告诉你是有哪个进程造成的,但也有可能不知道,需要我们手动排查。

如果是在面试场景中,这个问题可能不需要确认,毕竟 Java 面试,面试官可能直接就告诉你是 Java 占用的 CPU 过高。

这一步也非常简单,就是一个 top命令而已,基本上所有同学都用过这个命令吧。

a834b14fd380a429748bffaa6b12627e.png

使用 top命令发现占用 CPU 99.7% 的线程是 Java 进程,进程 PID 为 13731。

第二步,用 top -Hp 命令查看占用 CPU 最高的线程

上一步用 top命令找到了那个 Java 进程。那一个进程中有那么多线程,不可能所有线程都一直占着 CPU 不放,这一步要做的就是揪出这个罪魁祸首,当然有可能不止一个。

执行top -Hp pid命令,pid 就是前面的 Java 进程,我这个例子中就是 13731 ,完整命令为:

top -Hp 13731,执行之后的效果如下

151ff848873f7647699d6056f054a9fb.png

可以看到占用 CPU 最高的那个线程 PID 为 13756。

然后将 13756转换为 16 进制的,后面会用到,可以用在线进制转换的网站直接转换,转换结果为 0x35bc;

也可以直接输入命令转换,printf "%x" 线程id,如下图

20201117222417338433.png

第三步,保存线程栈信息

当前 Java 程序的所有线程信息都可以通过 jstack命令查看,我们用jstack命令将第一步找到的 Java 进程的线程栈保存下来。

jstack 13731 > thread_stack.log

第四步,在线程栈中查找最贵祸首的线程

第二步已经找到了这个罪魁祸首的线程 PID,并把它转换成了 16 进制的,第三步保存下来的线程栈中有所有线程的 PID 16 进制信息,我们在线程栈中查找这个16进制的线程 id (0x35bc)。

a35259f323ff0e3b1924c1719cb0d45d.png

怎么样,现在一目了然了,线程名称、线程状态、以及哪行代码消耗了最多的 CPU 都很清楚了。

3.实战演练

昨天刚好测试反馈说我们的转测环境上存在cpu占用过高的情况,于是刚好按照以上步骤进行验证下:

1.先执行top命令,截取部分图如下:

20201117222417385308.png

可以看到50262这个进程导致的cpu过高,并且是java程序,最后一列

2.执行top -Hp pid命令,查看具体的线程

20201117222417447808.png

20201117222417557183.png

可以看到是52018这个线程占用了cpu过高的使用率,使用在线进制转换,将其转为16进制,结果为cb8c,即0xcb8c.

在线进制转换地址

3.使用jstack将进程内的线程栈信息保存

由于转测环境没有保存权限,我直接展示到桌面复制出来后进行的搜索查询,这里仅截取部分片段

20201117222417588433.png

根据第二步中的16进制线程id查询信息,内容如下:

"Thread-8" #27 daemon prio=5 os_prio=0 tid=0x00007f692684d000 nid=0xcb8c runnable [0x00007f6940109000]

java.lang.Thread.State: RUNNABLE

at java.util.HashMap.putVal(HashMap.java:629)

at java.util.HashMap.put(HashMap.java:612)

at java.util.HashSet.add(HashSet.java:220)

at java.util.AbstractCollection.addAll(AbstractCollection.java:344)

at java.util.HashSet.(HashSet.java:120)

at com.huawei.ivas.externals.config.DataSourceRoutingCache.getAllDatasources(DataSourceRoutingCache.java:140)

at com.huawei.ivas.externals.config.TaskLoadBalanceCache.getNodeArray(TaskLoadBalanceCache.java:196)

at com.huawei.ivas.service.comm.sms.receiver.RbtSmsProcessThread.run(RbtSmsProcessThread.java:68)

~~

可以看到具体的导致问题的代码和行号,我们搜索RbtSmsProcessThread这个类,并定位到68行:

![](https://img2020.cnblogs.com/blog/1673559/202011/1673559-20201117165104479-1009344550.png)

至此定位到导致占用cpu过高的问题代码

原文:https://www.cnblogs.com/lovelywcc/p/13995883.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux 中的 CPU 使用率过时,可以按照以下步骤来排查问题: 1. 使用 top 或 htop 命令查看当前 CPU 使用情况: ``` top ``` 或 ``` htop ``` 这些命令将显示当前运行中的进程及其 CPU 使用率。按下 "1" 键可以查看每个 CPU 核心的使用情况。 2. 检查哪些进程占用了大量的 CPU 资源: 在 top 或 htop 界面中,按下 "Shift + P" 键,可以按 CPU 使用率对进程进行排序。这样可以找到占用 CPU 资源较多的进程。 3. 查看进程的详细信息: 在 top 或 htop 界面中,选择一个占用 CPU 的进程,按下 "F" 键,然后选择 "P"(按 CPU 使用率排序),"C"(显示进程命令行),"T"(按进程运行时间排序)等选项,可以查看进程的详细信息。 4. 检查系统负载情况: 使用 uptime 命令查看系统负载情况: ``` uptime ``` 如果负载过,表示系统中正在运行的进程过多,可能导致 CPU 资源紧张。 5. 检查系统日志: 使用 dmesg 命令查看系统日志,查找是否有异常或错误信息: ``` dmesg ``` 或者查看特定的日志文件,如 /var/log/syslog 或 /var/log/messages: ``` tail -n 100 /var/log/syslog ``` 6. 排查可能的问题: - 检查是否有恶意软件或病毒感染。 - 检查是否有不正常的进程或服务运行。 - 检查是否有配置错误或不合理的应用程序。 - 检查是否有大量的网络流量导致 CPU 负载过。 - 检查是否有磁盘 I/O 瓶颈导致 CPU 资源被阻塞。 根据具体情况,采取相应的措施来解决 CPU 使用率过的问题。可能需要停止或重启占用大量 CPU 资源的进程,优化应用程序配置,增加硬件资源等。如果问题持续存在,可以考虑进行性能分析和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值