惊悚,单个java进程占用700%的CPU
背景
最近负责的一个项目上线,运行一段时间后发现对应的进程竟然占用了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相关推荐
- Java进程占用CPU资源过多分析
问题描述: 生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 问题分析: 1,程序属于CPU密集型,和开发沟通 ...
- linux下查找java进程占用CPU过高原因
linux下查找java进程占用CPU过高原因 1. 查找进程 top查看进程占用资源情况 明显看出java的两个进程22714,12406占用过高cpu. 2.查找线程 使用top -H -p &l ...
- 趣味编程故事|java进程占用cpu过高怎么办,别急我来帮你
关注公众号"AI码师"领取2021最新面试资料一份 [主演] 运维小哥:小李 测试小姐姐:小红 开发人员:本色出演 [剧情] 在一个阳光明媚的清晨,原本还在睡梦中的我,被小李(运维 ...
- Java进程占用内存超高分析
Java进程占用内存超高分析_ 1. 报错 2. 解决 3. 我用到的解决方法 写了一个Java服务,没有定时服务,没有线程池,没有重度的读写,只是对外提供了几个接口,接口的访问量并不高,结果占用内存 ...
- Java进程占用内存过高,排查解决方法
Java进程占用内存过高,排查解决方法 参考文章: (1)Java进程占用内存过高,排查解决方法 (2)https://www.cnblogs.com/eeexu123/p/10913389.html ...
- ps aux排序 (查看进程占用内存和cpu)
查看进程占用内存和cpu: ps aux排序 按内存升序排列: ps aux --sort=+rss 按内存降序排列: ps aux --sort=-rss 按cpu升序排列: ps aux --so ...
- 排查解决Java进程占用内存过高
排查解决Java进程占用内存过高 1 在项目部署运行之前 1 检查JVM参数设置 2 检查代码逻辑 3 使用内存分析工具 4 检查线程 5 调整应用程序的设计 7 调整硬件资源 2 在项目部署运行之后 ...
- 查看java进程占用内存_如何查看java进程大批占用内存
如何查看java进程大量占用内存 你好,方法如下: 可以直接使用top命令后,查看%MEM的内容.可以选择按进程查看或者按用户查看,如想查看oracle用户的进程内存使用情况的话可以使用如下的命令: ...
- java 进程占用系统内存过高分析
JVM的内存 先放一张JVM的内存划分图,总体上可以分为堆和非堆(粗略划分,基于java8) 那么一个Java进程最大占用的物理内存为: Max Memory = eden + survivor + ...
最新文章
- Udacity机器人软件工程师课程笔记(二十四) - 控制(其二) - PID优化,梯度下降算法,带噪声的PID控制
- 300 Longest Increasing Subsequence
- android高仿微信拍照、多选、预览、删除(去除相片)相冊功能
- python colormap(颜色映射)自定义
- 数字图像处理——第四章 频率域图像增强
- 安卓 spinner下拉框 做模糊查询_如何用一张图来做全年/去年的部门离职率动态对比...
- Java程序员从笨鸟到菜鸟之(七十三)细谈Spring(五)spring之AOP底层大揭秘
- rnn按时间展开_作词家下岗系列:教你用 RNN 算法做一个写词软件
- 常见的权限访问控制模型
- 再聊一次值类型和引用类型
- decimal类型对象里面定义什么类型_奥斯塔罗 单身开启桃花雷达 现阶段的我适合什么类型的对象?...
- 大数据产品的备份及恢复
- 【linux高级程序设计】(第十三章)Linux Socket网络编程基础 2
- Android官方开发文档Training系列课程中文版:创建自定义View之View的优化
- 《R语言机器学习:实用案例分析》——1.2节R的数据结构
- 贪心算法——部分背包(洛谷 P2240)
- supervisor管理mysql靠谱吗_Supervisor 从入门到放弃
- 16个最有趣汉字,说透为人处世
- Python 查询 MAC 地址相关信息
- 计算机系统的日常运行维护,浅谈计算机系统的日常维护管理