Java进程CPU高负载排查

Java进程CPU高负载排查步骤_java进程cpu使用率高排查_YouluBank的博客-CSDN博客
【问题定位】使用arthas定位CPU高的问题_arthas cpu高_秋装什么的博客-CSDN博客

CPU飙升可能原因

  1. CPU 上下文切换过多。
    1. 对于 CPU 来说,同一时刻下每个 CPU 核心只能运行-个线程,如果有多个线程要执行,CPU 只能通过上下文切换的方式来执行不同的线程。
    2. 上下文切换需要做两个事情:保存运行线程的执行状态;让处于等待中的线程执行
    3. 这两个过程需要 CPU 执行内核相关指令实现状态保存,如果较多的上下文切换会占据大量 CPU 资源,从而使得 cpu 无法去执行用户进程中的指令,导致响应速度下降。
  2. 在 Java 中,文件1O、网络 1O、锁等待、线程阻塞等操作都会造成线程阻塞从而触发上下文切换
  3. CPU 资源过度消耗,也就是在程序中创建了大量的线程,或者有线程一直占用CPU 资源无法被释放,比如死循环!
  4. CPU 利用率过高之后,导致应用中的线程无法获得 CPU 的调度,从而影响程序的执行效率!

使用命令查找

采用top命令定位进程

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

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

使用top -Hp命令定位线程

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

top -Hp 29706

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

使用jstack命令定位代码

线程号转换为16进制

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

printf "%x\n"  30309

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

采用jstack命令导出线程快照

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

jstack -l 29706 > ./jstack_result.txt

根据线程号定位具体代码

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

cat jstack_result.txt |grep -A 100  7665

image.png
根据搜索结果,判断应该是ImageConverter.run()方法中的代码出现问题
也可以直接采用jstack |grep -A 200 来定位具体代码

jstack 29706<
<think>嗯,用户之前问过关于如何使用jstack下载的问题,现在他们想了解如何用top和jstack排查CPUJava进程。我需要确保回答结构清晰,分步骤解释,并且结合之前的指南内容。 首先,用户可能已经安装了JDK,所以可能不需要再重复安装步骤,但可能需要确认环境变量是否正确设置。接着,需要解释如何用top找到CPUJava进程,然后使用jstack分析线程情况。 用户可能对Linux命令不太熟悉,所以步骤要详细,比如如何用top查看进程,如何转换线程模式,如何找到占用的线程ID。然后,将线程ID转换为十六进制,以便在jstack输出中查找对应的堆栈信息。 另外,用户可能需要知道如何分析线程堆栈,识别问题代码,比如死循环、阻塞操作等。还要注意权限问题,可能需要sudo执行jstack。此外,可以推荐其他工具如jcmd或arthas作为补充,这部分在之前的回答里提到过,需要保持一致性。 需要避免使用复杂术语,用中文简单解释每个步骤的目的,例如为什么需要线程ID转换,如何通过堆栈定位代码。还要提醒常见问题,比如权限不足或者JDK路径问题,参考之前的问题解决部分。 最后,确保LaTeX格式正确,行内代码用反引号,独立代码块用三个反引号,但用户要求使用$...$和$$...$$,不过在这里可能主要是代码块,所以按之前的格式处理。检查是否有遗漏的步骤,比如是否需要多次抓取jstack快照对比,或者结合其他日志分析。 总结下来,回答应该分步骤,从定位进程到分析线程,再到定位代码,结合示例命令和输出,帮助用户逐步排查CPU问题。同时,注意与之前回答的衔接,比如环境变量配置和工具推荐,保持信息一致。</think>--- ### 分步排查CPUJava进程(结合`top`与`jstack`) --- #### **Step 1:定位CPUJava进程** 使用`top`命令快速筛选目标进程: ```bash # 启动top后按以下键位操作 1️⃣ 输入大写`P`:按CPU使用率排序 2️⃣ 输入`c`:显示完整命令行(确认Java进程) 3️⃣ 输入`H`:切换到线程模式(查看具体线程) ``` *示例输出片段:* ``` PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1234 app 20 0 12.3g 2.1g 15m S 198.3 6.7 10:30.9 java -Xmx4g ... ``` --- #### **Step 2:获取问题线程的十进制PID** 在`top`线程模式下: - 记录CPU的线程PID(例如`5678`) - **关键操作**:将十进制PID转为十六进制(用于匹配jstack输出) ```bash # 使用printf快速转换 printf "%x\n" 5678 # 输出示例:162e ``` --- #### **Step 3:生成线程堆栈快照** 通过`jstack`导出线程状态(需JDK环境): ```bash # 抓取进程的快照(PID=1234) jstack 1234 > thread_dump.log # 若权限不足,添加用户参数 sudo -u <进程所属用户> jstack 1234 > thread_dump.log ``` --- #### **Step 4:关联CPU高负载线程** 在`thread_dump.log`中搜索十六进制线程ID(`nid=0x162e`): ```text "main" #1 prio=5 os_prio=0 tid=0x00007f4874009800 nid=0x162e runnable [0x00007f487d1fe000] java.lang.Thread.State: RUNNABLE at com.example.LoopService.infiniteLoop(LoopService.java:42) at com.example.Main.run(Main.java:15) ``` *关键字段解析*: - `nid=0x162e`:对应top中CPU线程的十六进制PID - `Thread.State`:线程状态(RUNNABLE/BLOCKED等) - 堆栈调用链:定位到具体代码行(例如`LoopService.java:42`) --- #### **Step 5:典型问题代码模式** 通过线程状态快速判断问题类型: | 线程状态 | 常见问题场景 | 代码特征 | |-------------|-----------------------------|-----------------------------| | **RUNNABLE**| CPU密集型操作 | 死循环、复杂算法、未休眠的轮询 | | **BLOCKED** | 资源竞争 | synchronized锁竞争、数据库锁 | | **WAITING** | 线程挂起 | wait()/join()未唤醒、I/O阻塞 | --- ### 增强排查技巧 #### **技巧1:连续抓取快照对比** ```bash # 每隔2秒抓取3次快照(观察线程状态变化) for i in {1..3}; do jstack 1234 > dump_$i.log; sleep 2; done ``` #### **技巧2:结合`jstat`监控GC** ```bash # 检查GC是否频繁(间隔1秒,输出10次) jstat -gcutil 1234 1000 10 # 输出字段说明: S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 99.99 68.45 98.33 95.12 90.20 120 15.234 5 3.456 18.690 ``` *`FGC`(Full GC次数)或`FGCT`(Full GC时间)可能引发CPU飙升* --- ### 替代方案推荐 #### **方案1:使用`jcmd`快速诊断** ```bash # 列出所有Java进程 jcmd -l # 生成线程转储(等效于jstack) jcmd 1234 Thread.print > thread_dump.log ``` #### **方案2:Arthas实时分析** ```bash # 启动Arthas并附加到进程 ./arthas-boot.jar 1234 # 执行线程CPU占比统计 thread -n 3 # 显示CPU的3个线程 ``` --- ### 注意事项 1. **权限问题**:生产环境操作需获得授权,避免影响服务 2. **快照时间**:尽量在CPU峰时抓取快照 3. **混合模式**:若涉及JNI代码,添加`-m`参数捕获本地栈 ```bash jstack -m 1234 > native_stack.log ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值