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

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

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

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

这就是一个套路题,所谓套路题就是有标准的套路解法的,掌握了套路,不仅能解决面试官,还能解决问题。不然真的就掉进套路里了。

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

模拟一个高 CPU 场景

先用一段程序创建几个线程,将其中一个线程设置成高 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 。

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

排查步骤

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

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

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

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

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

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

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

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

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

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

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

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

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

第三步,保存线程栈信息

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

jstack 13731 > thread_stack.log

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

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

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

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

这位英俊潇洒的少年,如果觉得还不错的话,给个推荐可好!

公众号「古时的风筝」,Java 开发者,全栈工程师,bug 杀手,擅长解决问题。
一个兼具深度与广度的程序员鼓励师,本打算写诗却写起了代码的田园码农!坚持原创干货输出,你可选择现在就关注我,或者看看历史文章再关注也不迟。长按二维码关注,跟我一起变优秀!

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

Original: https://www.cnblogs.com/fengzheng/p/13935066.html
Author: 风的姿态
Title: 线上Java程序占用 CPU 过高,请说一下排查方法?

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/539532/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 群晖安装docker 安装neuxs3

    群晖docker 文件夹下创建 docker 下载neuxs3 启动容器 映射端口3003:8081 群晖反向代理。不用https的这一步可以不用,之间路由转发端口3003就行 路…

    Java 2023年6月6日
    087
  • spring中反射工具类

    安扫提示field.setAccessible(true)漏洞问题(java Spring) 采用 org.springframework.util.ReflectionUtils…

    Java 2023年5月30日
    073
  • Java RMI详解

    RMI:远程方法调用(Remote Method Invocation)。能够让在某个java虚拟机上的对象像调用本地对象一样调用另一个java 虚拟机中的对象上的方法。 RMI远…

    Java 2023年5月29日
    086
  • springboot修改打包后的项目(jar war)名称

    springboot修改打包后的项目(jar war)名称 在build里面添加inalName,指定好想要额项目名称即可: Original: https://www.cnblo…

    Java 2023年5月30日
    078
  • spring boot集成mybatis 自动生成实体类和mapper文件、Dao层

    1.创建spring boot集成mybatis请见 2.在resources目录下新键mybatis-generator文件夹,并在文件夹中新键mybatis-generator…

    Java 2023年5月30日
    057
  • 消息队列rabbitmq

    为什么用消息队列 举例 &#x6BD4;&#x5982;&#x5728;&#x4E00;&#x4E2A;&#x4F01;&#…

    Java 2023年5月30日
    084
  • 教你win7系统手动导入注册表获取管理员权限

    想必大家都遇到过win7系统手动导入注册表获取管理员权限的问题吧,大多数朋友还不知道怎么处理固然处理起来也不难,然而还是有一些小伙伴不明白win7系统手动导入注册表获取管理员权限应…

    Java 2023年5月30日
    093
  • ftp多文件压缩下载

    @GetMapping(value = "/find") public String findfile(String filePath, String file…

    Java 2023年6月9日
    073
  • 崔用志-微信开发-java版本

    崔用志-微信开发-java版本 今天看到一些关于微信开发的知识蛮好的博客,分享给大家,希望对大家有帮助。 总结来自:http://www.cuiyongzhi.com/ Origi…

    Java 2023年5月29日
    073
  • Java虚拟机启动过程解析

    当我们在编写Java应用的时候,很少会注意Java程序是如何被运行的,如何被操作系统管理和调度的。带着好奇心,探索一下Java虚拟机启动过程。 从 Java&#x6E90;…

    Java 2023年6月6日
    0117
  • 深入浅出SpringSecurity

    SpringSecurity学习 SpringSecurity简介 安全框架的概述 什么是安全框架?是为了解决安全问题的框架。如果没有安全框架,我们需要手动处理每个资源的访问控制,…

    Java 2023年6月5日
    0119
  • iphone 开发学习笔记七

    本篇算是该系列最后一篇,虽不能说是很熟,但使用MonoTouch 开发的其本方法是掌握了,主要是完成当初的任务,实现地图开发包在iPhone上的实现。使用MonoTouch ,.N…

    Java 2023年5月29日
    052
  • Redis的安装使用

    @Test public void testKey() throws Exception { //创建客户端指定连接服务器端主机ip和端口,端口不指定时默认使用6379 Jedis…

    Java 2023年6月7日
    079
  • redis分析系列之set命令

    前言 最近研究下redis源码,现在从最基本的命令行操作来分析,redis是如何处理命令操作的 redis的set命令操作 我们在redis-cli执行下面的命令 java;gut…

    Java 2023年6月5日
    098
  • Java8新特性系列-Date Time API

    在 Java 8 中,引入了一个新的日期时间 API,以弥补旧日期时间 API 的以下缺点。 不是线程安全的 – java.util.Date 不是线程安全的,因此开发人员在使用日…

    Java 2023年6月7日
    069
  • Centos7:maven打包构建项目失败,No compiler is provided in this environment.Perhaps。。。

    环境: Centos7 如果你输入 javac -version,没有显示版本信息,那么大概率解决方法是这个 yum install java-devel安装原生的: 再次运行 m…

    Java 2023年6月7日
    082
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球