背景

最近负责的一个项目上线,运行一段时间后发现对应的进程竟然占用了700%的CPU,导致公司的物理服务器都不堪重负,频繁宕机。
那么,针对这类java进程CPU飙升的问题,我们一般要怎么去定位解决呢?


一、采用top命令定位进程

登录服务器,执行top命令,查看CPU占用情况,找到进程的pid

top


很容易发现,PID为29706的java进程的CPU飙升到700%多,且一直降不下来,很显然出现了问题。

二、使用top -Hp命令定位线程

使用 top -Hp <pid> 命令(为Java进程的id号)查看该Java进程内所有线程的资源占用情况(按shft+p按照cpu占用进行排序,按shift+m按照内存占用进行排序)
此处按照cpu排序:

top -Hp 23602


很容易发现,多个线程的CPU占用达到了90%多。我们挑选线程号为30309的线程继续分析。

三、使用jstack命令定位代码

1.线程号转换为16进制

printf “%x\n” 命令(tid指线程的id号)将以上10进制的线程号转换为16进制:

printf "%x\n"  30309


转换后的结果分别为7665,由于导出的线程快照中线程的nid是16进制的,而16进制以0x开头,所以对应的16进制的线程号nid为0x7665

2.采用jstack命令导出线程快照

通过使用dk自带命令jstack获取该java进程的线程快照并输入到文件中: jstack -l > ./jstack_result.txt 命令(为Java进程的id号)来获取线程快照结果并输入到指定文件。

jstack -l 29706 > ./jstack_result.txt

3.根据线程号定位具体代码

在jstack_result.txt 文件中根据线程好nid搜索对应的线程描述

cat jstack_result.txt |grep -A 100  7665


根据搜索结果,判断应该是ImageConverter.run()方法中的代码出现问题

PS

这里也可以直接采用jstack <pid> |grep -A 200 <nid>来定位具体代码

$jstack 44529 |grep -A 200 ae24
"System Clock" #28 daemon prio=5 os_prio=0 tid=0x00007efc19e8e800 nid=0xae24 waiting on condition [0x00007efbe0d91000]java.lang.Thread.State: TIMED_WAITING (sleeping)at java.lang.Thread.sleep(Native Method)at java.lang.Thread.sleep(Thread.java:340)at java.util.concurrentC.TimeUnit.sleep(TimeUnit.java:386)at com.*.order.Controller.OrderController.detail(OrderController.java:37)  //业务代码阻塞点

四、分析代码解决问题

下面是ImageConverter.run()方法中的部分核心代码。
逻辑说明:
在while循环中,不断读取堵塞队列dataQueue中的数据,如果数据为空,则执行continue进行下一次循环。如果不为空,则通过poll()方法读取数据,做相关逻辑处理。

//存储minicap的socket连接返回的数据   (改用消息队列存储读到的流数据) ,设置阻塞队列长度,防止出现内存溢出
//全局变量
private BlockingQueue<byte[]> dataQueue = new LinkedBlockingQueue<byte[]>(100000);//消费线程
@Override
public void run() {//long start = System.currentTimeMillis();while (isRunning) {//分析这里从LinkedBlockingQueueif (dataQueue.isEmpty()) {continue;}byte[] buffer = device.getMinicap().dataQueue.poll();int len = buffer.length;
}

初看这段代码好像每什么问题,但是如果dataQueue对象长期为空的话,这里就会一直空循环,导致CPU飙升。
那么如果解决呢?
分析LinkedBlockingQueue阻塞队列的API发现:

//取出队列中的头部元素,如果队列为空则调用此方法的线程被阻塞等待,直到有元素能被取出,如果等待过程被中断则抛出InterruptedException
E take() throws InterruptedException;//取出队列中的头部元素,如果队列为空返回null
E poll();

这两种取值的API,显然take方法更时候这里的场景。

代码修改为:

while (isRunning) {/* if (device.getMinicap().dataQueue.isEmpty()) {continue;}*/byte[] buffer = new byte[0];try {buffer = device.getMinicap().dataQueue.take();} catch (InterruptedException e) {e.printStackTrace();}
……
}

重启项目后,测试发现项目运行稳定,对应项目进程的CPU消耗占比不到10%。

CPU飙升的常见原因:

1.空循环,本文中的问题其实就这个原因导致的。
2.在循环的代码逻辑中,创建大量的新对象导致频繁GC
3.在循环的代码逻辑中进行大量无意义的计算。
简单来说,遇见CPU飙升的问题,就要仔细检查相关线程代码中的循环逻辑,比如for,while等。


总结

CPU飙升问题定位的一般步骤是:
1.首先通过top指令查看当前占用CPU较高的进程PID;
2.查看当前进程消耗资源的线程PID: top -Hp PID
3.通过print命令将线程PID转为16进制,根据该16进制值去打印的堆栈日志内查询,查看该线程所驻留的方法位置。
4.通过jstack命令,查看栈信息,定位到线程对应的具体代码。
5.分析代码解决问题。

参考:
https://blog.csdn.net/qq_21127151/article/details/105554734
https://www.cnblogs.com/fengweiweicoder/p/10992043.html

更多精彩,关注我吧。

惊悚,单个java进程占用700%的CPU相关推荐

  1. Java进程占用CPU资源过多分析

    问题描述: 生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 问题分析: 1,程序属于CPU密集型,和开发沟通 ...

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

    linux下查找java进程占用CPU过高原因 1. 查找进程 top查看进程占用资源情况 明显看出java的两个进程22714,12406占用过高cpu. 2.查找线程 使用top -H -p &l ...

  3. 趣味编程故事|java进程占用cpu过高怎么办,别急我来帮你

    关注公众号"AI码师"领取2021最新面试资料一份 [主演] 运维小哥:小李 测试小姐姐:小红 开发人员:本色出演 [剧情] 在一个阳光明媚的清晨,原本还在睡梦中的我,被小李(运维 ...

  4. Java进程占用内存超高分析

    Java进程占用内存超高分析_ 1. 报错 2. 解决 3. 我用到的解决方法 写了一个Java服务,没有定时服务,没有线程池,没有重度的读写,只是对外提供了几个接口,接口的访问量并不高,结果占用内存 ...

  5. Java进程占用内存过高,排查解决方法

    Java进程占用内存过高,排查解决方法 参考文章: (1)Java进程占用内存过高,排查解决方法 (2)https://www.cnblogs.com/eeexu123/p/10913389.html ...

  6. ps aux排序 (查看进程占用内存和cpu)

    查看进程占用内存和cpu: ps aux排序 按内存升序排列: ps aux --sort=+rss 按内存降序排列: ps aux --sort=-rss 按cpu升序排列: ps aux --so ...

  7. 排查解决Java进程占用内存过高

    排查解决Java进程占用内存过高 1 在项目部署运行之前 1 检查JVM参数设置 2 检查代码逻辑 3 使用内存分析工具 4 检查线程 5 调整应用程序的设计 7 调整硬件资源 2 在项目部署运行之后 ...

  8. 查看java进程占用内存_如何查看java进程大批占用内存

    如何查看java进程大量占用内存 你好,方法如下: 可以直接使用top命令后,查看%MEM的内容.可以选择按进程查看或者按用户查看,如想查看oracle用户的进程内存使用情况的话可以使用如下的命令: ...

  9. java 进程占用系统内存过高分析

    JVM的内存 先放一张JVM的内存划分图,总体上可以分为堆和非堆(粗略划分,基于java8) 那么一个Java进程最大占用的物理内存为: Max Memory = eden + survivor + ...

最新文章

  1. Udacity机器人软件工程师课程笔记(二十四) - 控制(其二) - PID优化,梯度下降算法,带噪声的PID控制
  2. 300 Longest Increasing Subsequence
  3. android高仿微信拍照、多选、预览、删除(去除相片)相冊功能
  4. python colormap(颜色映射)自定义
  5. 数字图像处理——第四章 频率域图像增强
  6. 安卓 spinner下拉框 做模糊查询_如何用一张图来做全年/去年的部门离职率动态对比...
  7. Java程序员从笨鸟到菜鸟之(七十三)细谈Spring(五)spring之AOP底层大揭秘
  8. rnn按时间展开_作词家下岗系列:教你用 RNN 算法做一个写词软件
  9. 常见的权限访问控制模型
  10. 再聊一次值类型和引用类型
  11. decimal类型对象里面定义什么类型_奥斯塔罗 单身开启桃花雷达 现阶段的我适合什么类型的对象?...
  12. 大数据产品的备份及恢复
  13. 【linux高级程序设计】(第十三章)Linux Socket网络编程基础 2
  14. Android官方开发文档Training系列课程中文版:创建自定义View之View的优化
  15. 《R语言机器学习:实用案例分析》——1.2节R的数据结构
  16. 贪心算法——部分背包(洛谷 P2240)
  17. supervisor管理mysql靠谱吗_Supervisor 从入门到放弃
  18. 16个最有趣汉字,说透为人处世
  19. Python 查询 MAC 地址相关信息
  20. 计算机系统的日常运行维护,浅谈计算机系统的日常维护管理

热门文章

  1. 组态软件的运行策略控制
  2. Guitar Pro最新 音频汉化编辑软件免费中文版
  3. html兼容qsv格式,qsv压缩画质都能吊打软压了吗
  4. 浅谈UI #剪辑软件
  5. 华为android界面强刷救砖教程,华为手机救砖教程 一键救砖 华为手机怎么救砖
  6. 查找CAD图纸中的坐标
  7. jenkins+gitlab实现自动化部署平台
  8. 成都前端平均薪资水平?
  9. 元器件的非线性与线性
  10. 移动app实用测试指南