java程序cpu飙高定位

news2024/9/20 1:04:38

1 定位过程

CPU飙升问题定位的一般步骤是:

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

2 常见原因及解决方案

  1. 如果是空循环,或者空自旋。

    处理方式:可以使用Thread.sleep或者加锁,让线程适当的阻塞。

  2. 在循环的代码逻辑中,创建大量的新对象导致频繁GC。比如,从mysql查出了大量的数据,比如100W以上等等。

    处理方式:可以减少对象的创建数量,或者,可以考虑使用 对象池。

  3. 其他的一些造成CPU飙升的场景,比如 selector空轮训导致CPU飙升 。

    处理方式:参考Netty源码,无效的事件查询到了一定的次数,进行 selector 重建。

3 正式案例

3.1 采用top命令定位进程

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

top

在这里插入图片描述

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

3.2 使用top -Hp命令定位线程

使用 top -Hp <pid> 命令(为Java进程的id号)查看该Java进程内所有线程的资源占用情况

tip: 按shft+p按照cpu占用进行排序,按shift+m按照内存占用进行排序

top -Hp 29706

在这里插入图片描述

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

3.3 使用jstack命令定位代码

3.3.1 线程号转换为16进制

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

printf "%x\n"

在这里插入图片描述

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

3.3.2 采用jstack命令导出线程快照

通过使用jdk自带命令jstack获取该java进程的线程快照并输入到文件中

注意:open jdk不带该命令|没有注册环境变量的,需要对应的java目录执行jstack命令

 jstack -l 进程ID > ./jstack_result.txt 

命令(为Java进程的id号)来获取线程快照结果并输入到指定文件

jstack -l 29706 > ./jstack_result.txt

3.3.3 根据线程号定位具体代码

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

cat jstack_result.txt |grep -A 100  7665

在这里插入图片描述

3.4 分析代码解决问题

下面是ImageConverter.run()方法中的部分核心代码。

逻辑说明:

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

在while循环中,不断读取堵塞队列dataQueue中的数据,如果数据为空,则执行continue进行下一次循环。

如果不为空,则通过poll()方法读取数据,做相关逻辑处理。

初看这段代码好像每什么问题,但是如果dataQueue对象长期为空的话,这里就会一直空循环,导致CPU飙升。

那么如果解决呢?

//取出队列中的头部元素,如果队列为空则调用此方法的线程被阻塞等待,直到有元素能被取出,如果等待过程被中断则抛出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%

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XjmRhZiD-1675222868841)(image/d1cccf29d4c87d03b09c8d3face46c78.png)]

本文案例取之网上,公司代码敏感

4 部分脚本代码

dumpapp(){
  echo "应用dump:=============start========================"
  is_exist
  if [ $? -eq 1 ];then
    echo "${appName} is not running"
    exit 0
  fi
  echo "${appName} Process ID is : $pid"
  echo "${appName} Process ID is : $pid" > ${logsPath}/${appName}_${pid}_${caijiTime}.txt
  #CUP top cupNum的数据写入临时文件
  ps p ${pid} -L -o pcpu,pid,tid,time | sort -f -k4 | tail -n -${cupNum} | grep -E ':'> ${logsPath}/temp.txt
  echo "   "
  echo "CPU TOP ${cupNum} :"
  echo "CPU TOP ${cupNum} :" >> ${logsPath}/${appName}_${pid}_${caijiTime}.txt
  cat ${logsPath}/temp.txt
  cat ${logsPath}/temp.txt >> ${logsPath}/${appName}_${pid}_${caijiTime}.txt
  echo "   "

  processId=`awk '{print $3}' ${logsPath}/temp.txt`
  echo "${processId}" > ${logsPath}/temp.txt

  while read LINE
  do
    tempId=`printf "%x" ${LINE}`
    echo "线程${LINE}对应的十六进制编码是:${tempId}"
    echo "线程${LINE}对应的十六进制编码是:${tempId}" >> ${logsPath}/${appName}_${pid}_${caijiTime}.txt
  done < ${logsPath}/temp.txt

  rm -rf ${logsPath}/${pid}.log
  rm -rf ${logsPath}/${pid}.hprof
  ${jdkPath}/jstack -l ${pid} > ${logsPath}/${appName}_${pid}_${caijiTime}.log
  ${jdkPath}/jmap -dump:format=b,file=${logsPath}/${appName}_${pid}_${caijiTime}.hprof ${pid}
  echo "Heap dump file Completion"
  echo "   "

  echo "log文件路径:${logsPath}/${appName}_${pid}_${caijiTime}.log"
  echo "hprof文件路径:${logsPath}/${appName}_${pid}_${caijiTime}.hprof"
  echo "log文件路径:${logsPath}/${appName}_${pid}_${caijiTime}.log" >> ${logsPath}/${appName}_${pid}_${caijiTime}.txt
  echo "hprof文件路径:${logsPath}/${appName}_${pid}_${caijiTime}.hprof" >> ${logsPath}/${appName}_${pid}_${caijiTime}.txt
  echo "应用dump:=============end========================"
  
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/190295.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Plecs电力电子仿真专业教程-第一季

Plecs电力电子仿真专业教程-第一季 第一章 Plecs是什么&#xff1f; 第一节 Plecs简介 Plecs是瑞士Plexim GmbH公司开发的系统级电力电子仿真软件PLECS。PLECS是一个用于电路和控制结合的多功能仿真软件&#xff0c;尤其适用于电力电子和传动系统。不管您是工业领域中的开发…

Lua 面向对象(详解)

Lua 面向对象&#xff08;详解&#xff09; 参考文章&#xff1a; https://blog.csdn.net/linxinfa/article/details/103254828 https://zhuanlan.zhihu.com/p/115159195 https://blog.codingnow.com/cloud/LuaOO https://blog.codingnow.com/2006/06/oo_lua.html Lua的面向对象…

Homekit智能家居DIY-智能插座

WiFi智能插座对于新手接触智能家居产品更加友好&#xff0c;不需要额外购买网关设备 很多智能小配件也给我们得生活带来极大的便捷&#xff0c;智能插座就是其中之一&#xff0c;比如外出忘记关空调&#xff0c;可以拿起手机远程关闭。 简单说就是&#xff1a;插座可以连接wi…

不再一个个试错,这众多的flex属性

流式布局 本篇我们将从流式布局的四大方面入手&#xff0c;旨在认识、了解、以至于掌握其特性及功能。 为什么要用&#xff1f; 在我们抛弃标准流、定位流以及浮动流之后&#xff0c;取而代之的是flex流式布局。以一种更加优雅的方式实现元素布局。 轴的定义 在开始说它的特…

C语言#if、##ifdef、#ifndef的用法详解

假如现在要开发一个C语言程序&#xff0c;让它输出红色的文字&#xff0c;并且要求跨平台&#xff0c;在 Windows 和 Linux 下都能运行&#xff0c;怎么办呢&#xff1f;这个程序的难点在于&#xff0c;不同平台下控制文字颜色的代码不一样&#xff0c;我们必须要能够识别出不同…

2023最新版easyrecovery数据恢复软件免费版测评

大家好&#xff0c;关于easyrecovery数据恢复软件免费版很多朋友都还不太明白&#xff0c;今天小编就来为大家分享关于easyrecovery数据恢复软件免费版下载使用的知识&#xff0c;希望对各位有所帮助&#xff01; EasyRecovery其实是目前为止我用的最喜欢的一款数据恢复软件&a…

C++string的模拟实现(上篇)

目录 一.命名空间的封装与交换函数模板 1.命名空间的封装与类的定义 2.交换函数模板 二.string类的四个重要默认成员函数 1.构造函数的类外定义&#xff1a; 2.析构函数在类外的定义 3.拷贝构造函数在类外的定义 4.赋值运算符重载在类外的定义 5.关于两个string对象…

在线 OJ 项目(一) · 项目介绍 · 进程与线程 · 实现编译运行模块

一、项目介绍二、导入依赖、创建基本项目结构导入依赖创建基本项目结构三、进程、线程的基础知识回顾四、封装操作进程的工具类五、实现 “编译运行” 模块 Task 类六、封装读写文件的方法修改 JDK 版本七、Task 类的实现八、整理一下项目列表一、项目介绍 项目实现一个在线 O…

煤矿AI智能视频分析识别系统 opencv

煤矿AI智能视频分析识别系统通过opencvpython 深度学习网络模型&#xff0c;对皮带跑偏、撕裂、堆煤、异物、非法运人、有煤无煤状态等异常情况&#xff0c;以及人员工服穿戴、反光衣、安全帽、睡岗离岗、打电话、抽烟等行为进行自动抓拍存档。OpenCV基于C实现&#xff0c;同时…

【正点原子FPGA连载】第二十八章Linux并发与竞争 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南

1&#xff09;实验平台&#xff1a;正点原子MPSoC开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id692450874670 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第二十八章Linux…

【splishsplash】Houdini粒子的导入与导出

Houdini粒子的导入与导出 Houdini导入到splish 在Houdini中使用file导入任意几何模型 使用points from volume采样点&#xff0c;使其粒子化 使用file导出粒子化之后的模型&#xff0c;后缀写bhclassic 创建json场景文件&#xff08;建议放到MyScences文件夹&#xff09; …

C语言指针是什么?

计算机中所有的数据都必须放在内存中&#xff0c;不同类型的数据占用的字节数不一样&#xff0c;例如 int 占用 4 个字节&#xff0c;char 占用 1 个字节。为了正确地访问这些数据&#xff0c;必须为每个字节都编上号码&#xff0c;就像门牌号、身份证号一样&#xff0c;每个字…

HTTP协议 | 青训营笔记

1、概述 HTTP协议&#xff0c;超文本传输协议 应用层的协议&#xff0c;基于TCP协议&#xff0c;简单可扩展&#xff08;可以自定义header&#xff09; 每个HTTP请求都可以分为请求和响应两个部分 无状态的&#xff08;不知道之前的请求是携带过什么信息&#xff09; 2、协…

【Qt】8.QPainter、高级设置、手动调用绘图事件、绘图设备、文件操作、文件信息

目录 QPainter 代码 widget.h widget.cpp 结果 高级设置 代码 widget.h widget.cpp 结果 手动调用绘图事件 代码 widget.h widget.cpp 结果 绘图设备 代码 widget.h widget.cpp 结果 文件操作 代码 widget.cpp 结果 文件信息 代码 widget.cpp 结果…

一文带你看懂健康管理系统----IPMI

目录 1. IPMI概述 2. IPMI系统设计 3. 主BMC模块设计 5. 从IPMI模块设计 6. 名词解释 6. 代码 1. IPMI概述 智能平台管理接口&#xff08;IPMI&#xff1a;Intelligent Platform Management Interface&#xff09;是一项应用于服务器管理系统设计的标准&#xff0c;由Int…

BSN-DDC基础网络详解(一):基础介绍

BSN-DDC基础网络推出已经一年了&#xff0c;得到了行业应用方和广大开发者的高度认可。一年中BSN产品技术团队也在根据市场业务需求不断更新功能服务&#xff0c;我们将通过本系列文章为大家系统化介绍DDC网络的功能和使用&#xff0c;为感兴趣的朋友提供学习帮助。BSN-DDC基础…

历史与今日的事件

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 1.2023年1月31日中国最新量子计算机“悟空”即将问世&#xff0c…

【34】C语言 | 动态内存管理

目录 1.为什么存在动态内存分配 2、动态内存函数的介绍 2.1 malloc和free 2.2 calloc 2.3 realloc 1.为什么存在动态内存分配 我们已经掌握的内存开辟方式有: int val 20; //在栈空间上开辟四个字节 char arr[n] {0}; //在栈空间上开辟10个节的连续空间 但是上述的开辟…

mPEG-SS-NHS甲氧基聚乙二醇-二硫键-琥珀酰亚胺酯

mPEG-SS-NHS甲氧基聚乙二醇-双硫键-活性酯 名称&#xff1a;甲氧基聚乙二醇-双硫键-琥珀酰亚胺酯 英文名称&#xff1a;mPEG-SS-NHS 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 用 途&#xff1a;仅供科研实验使用&#xff0c;不用于诊治 外观: 固体或粘性…

【c语言进阶】动态通讯录

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a; c语言学习 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对我…