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

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

1.场景模拟

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

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

  1. public static void main(String[] args) {
  2. for (int i = 0; i < 10; i++) {
  3. Thread thread = new Thread(() -> {
  4. System.out.println(Thread.currentThread().getName());
  5. try {
  6. Thread.sleep(30 * 60 * 1000);
  7. }catch (Exception e){
  8. e.printStackTrace();
  9. }
  10. });
  11. thread.setName("thread-" + i);
  12. thread.start();
  13. }
  14. Thread highCpuThread = new Thread(() -> {
  15. int i = 0;
  16. while (true) {
  17. i++;
  18. }
  19. });
  20. highCpuThread.setName("HighCpu");
  21. highCpuThread.start();
  22. }

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

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

在linux上运行一段代码

2.排查步骤


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

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

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

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

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

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

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

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

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

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

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

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

第三步,保存线程栈信息

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

  1. jstack 13731 > thread_stack.log

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

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

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

3.实战演练

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

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



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

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





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

在线进制转换地址

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

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



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

  1. "Thread-8" #27 daemon prio=5 os_prio=0 tid=0x00007f692684d000 nid=0xcb8c runnable [0x00007f6940109000]
  2. java.lang.Thread.State: RUNNABLE
  3. at java.util.HashMap.putVal(HashMap.java:629)
  4. at java.util.HashMap.put(HashMap.java:612)
  5. at java.util.HashSet.add(HashSet.java:220)
  6. at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
  7. at java.util.HashSet.<init>(HashSet.java:120)
  8. at com.huawei.ivas.externals.config.DataSourceRoutingCache.getAllDatasources(DataSourceRoutingCache.java:140)
  9. at com.huawei.ivas.externals.config.TaskLoadBalanceCache.getNodeArray(TaskLoadBalanceCache.java:196)
  10. at com.huawei.ivas.service.comm.sms.receiver.RbtSmsProcessThread.run(RbtSmsProcessThread.java:68)

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



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

服务器CPU又爆了?Linux快速排查Java程序占用CPU很高的方法的更多相关文章

  1. linux下分析java程序占用CPU、内存过高

    一.CPU过高分析 1)使用TOP命令查看CPU.内存使用状态可以发现CPU占用主要分为两部分,一部分为系统内核空间占用CPU百分比,一部分为用户空间占用CPU百分比.其中CPU状态中标示id的为空闲 ...

  2. Linux排查Java程序占用CPU很高的解决办法

    Java的工具集相当强大,学习成本也很低,处理线上问题时,jstack这个工具就比微软的windbg,好学好用很多,3步找出占用CPU很高的源所在.而windbg反人类的各种命令,实在不敢恭维. 故意 ...

  3. Linux排查java程序占用cpu过高的线程代码

    分几步骤: 1.通过top,查出占用CPU过高的java进程 ,比如: pid :6666 2.通过ps -mp 6666 -o THREAD,tid,time| sort -n -k1 -r 查看此 ...

  4. 线上Java程序占用 CPU 过高,请说一下排查方法?

    我是风筝,公众号「古时的风筝」,一个兼具深度与广度的程序员鼓励师,一个本打算写诗却写起了代码的田园码农! 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在 ...

  5. 记一次java程序占用cpu超高排查

    1.首先通过top命令查看占用cpu过高的pid #top top - 18:07:25 up 48 days,  1:07,  3 users,  load average: 11.94, 11.9 ...

  6. windows 排查javaWeb程序占用CPU过高问题(可追踪到问题代码所在行)

      1.情景展示 java虚拟机占用这么高的CPU,肯定不正常! 2.原因分析 第一个是tomcat,正在运行java项目: 第二个是eclipse,因为eclipse的运行依赖于java. 现在的问 ...

  7. windows下揪出java程序占用cpu很高的线程 并找到问题代码 死循环线程代码

    我的一个java程序偶尔会出现cpu占用很高的情况 一直不知道什么原因 今天终于抽时间解决了 系统是win2003 jvisualvm 和 jconsole貌似都只能看到总共占用的cpu 看不到每个线 ...

  8. windows下揪出java程序占用cpu很高的线程

    背景 天天搞java,这些监控也都知道,用过,但也没往细里追究.因为也没碰见这种问题,这次还是静下来走一遍流程吧.与网上基本一致,不过我区分了下linux和windows的不一样.我感觉基本是程序写成 ...

  9. linux下查找java进程占用CPU过高原因

    1. 查找进程 top查看进程占用资源情况 明显看出java的两个进程22714,12406占用过高cpu.   2.查找线程 使用top -H -p <pid>查看线程占用情况   3. ...

随机推荐

  1. 图解HTTP权威指南(五) | HTTP缓存

    作者简介 李先生(Lemon),高级运维工程师(自称),SRE专家(目标),梦想在35岁买一辆保时捷.喜欢钻研底层技术,认为底层基础才是王道.一切新技术都离不开操作系统(CPU.内存.磁盘).网络等. ...

  2. SQL Server批量向表中插入多行数据语句

    因自己学习测试需要,需要两个有大量不重复行的表,表中行数越多越好.手动编写SQL语句,通过循环,批量向表中插入数据,考虑到避免一致问题,设置奇偶行不同.个人水平有限,如有错误,还望指正. 语句如下: ...

  3. 配置Oracle数据库和监听随Linux系统自启动【转】

     配置Oracle数据库和监听随Linux系统自启动     在某些情况下需要在Linux操作系统上提供一种无人值守的随机启动Oracle的功能,目的也许仅仅是为了帮助那些对Oracle细节非常不关心 ...

  4. Token验证的流程及如何准确的判断一个数据的类型

    Token验证的流程: 1,客户端使用用户名跟密码请求登录:2,服务端收到请求,去验证用户名与密码:3,验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端:4,客户端收到 T ...

  5. 使用OpenCV进行简单的人像分割与合成

    图像合成 实现思路 通过背景建模的方法,对源图像中的动态人物前景进行分割,再将目标图像作为背景,进行合成操作,获得一个可用的合成影像. 实现步骤如下. 使用BackgroundSubtractorMO ...

  6. 日常采坑:.NET Core SDK版本问题

    1..NetCore SDK版本问题 .NetCore3.1 webapi 部署linux,遇到一个坑,开启的目录浏览功能失效,几番尝试发现是版本问题.本地sdk版本与linux安装的sdk版本不对应 ...

  7. 【排序基础】5、插入排序法 - Insertion Sort

    插入排序法 - Insertion Sort 文章目录 插入排序法 - Insertion Sort 插入排序设计思想 插入排序代码实现 操作:插入排序与选择排序的比较 简单记录-bobo老师的玩转算 ...

  8. 【ORA】ORA-01078和LRM-00109 解决方法

    今天切换到asm实例的时候,发现是一个空实例,尝试启动实例,结果报错ORA-01078和LRM-00109 SQL> startupORA-01078: failure in processin ...

  9. 【VNC】vnc远程连接的时候无法显示图像已解决

    介绍一个 VNC连接工具:iis7服务器管理工具 IIs7服务器管理工具可以批量连接并管理VNC服务器 作为服务器集成管理器,它最优秀的功能就是批量管理windows与linux系统服务器.vps.能 ...

  10. leetcode 470. 用 Rand7() 实现 Rand10() (数学,优化策略)

    题目链接 https://leetcode-cn.com/problems/implement-rand10-using-rand7/ 题意: 给定一个rand7()的生成器,求解如何产生一个rand ...