java profile cpu_Java进程高CPU使用调查方法简介

介绍

关于java进程占用cpu问题,一般都是想知道

哪个(些)线程使用了更多的cpu

哪个(些)方法使用了更多的cpu

本文给出一个非常简要的介绍并给出了各个方法的使用例子,更深入使用可参考相关文档。 我觉得这些方法简单实用,已经帮助我解决过几次问题(产品环境过慢,性能调优),希望对你也有帮助。

简要总结

目标

解决方式

说明

适用于

哪个(些)线程占用了很多的cpu

Step 1. 通过ps命令得到jvm的各个线程的cpu使用率(并排序)

Step 2. 通过jstack的输出,找到这个线程(Step1中各个线程都有线程号)

注意:Step1(ps)中线程号为10进制,Step2(jstack)中为16进制。人肉转换的话,可以使用在线工具 http://www.binaryhexconverter.com/hex-to-decimal-converter, 或者 printf "%x\n" decimalNumber 来获得16进制

产品环境

开发/测试环境

哪个(些)方法占用了很多的cpu - via jvisualvm

visualvm连接java 进程后

1. 点击Sample 标签

2. 开始你的测试,然后马上点击cpu按钮

3. cpu占用测试结束后,点击 Stop

4. 点击Snapshot暂存结果

5. 观察分析Snapshot结果

6. Snapshot结果可以保存

下面例子中,提供了截屏。使用方式比较简单直接。

另外:visualvm还支持使用类似的方式查看内存在检测期间的分配情况

ONLY 开发/测试环境

因为一般不允许通过visualvm连接产品环境。

哪个(些)方法占用了很多的cpu - via hprof

添加-agentlib:hprof=cpu=samples到你的java进程启动脚本中,开始测试。测试结束后,关闭java进程。java进程退出后,在当前目录形成一个文件java.hprof.txt。这个文件中,包含了cpu使用方法排名。

本文会提供一个例子输出供参考。

该输出并没有visualvm信息丰富、直观。只有在visualvm无法使用,或者必须background执行的时候,才推荐使用。

None

平时工作中,我几乎从来没用使用这种方法。因为开发环境中,visualvm更合适。生产环境中,hprof是不会被使用的。

这里列出来只是提供一个新的思路。

note: https://www.tablesgenerator.com/markdown_tables# could help to generate markdown table

note: for newline in markdown table, you have to input

特别例子 - 线程 thread.sleep, or readBytes from console,但是仍然CPU很高

E.g. High CPU while read lines from console: http://www.jianshu.com/p/4a6fe6c82311

E.g. 微信群中,有人提出在一台测试Tomcat(没有任何load),但是cpu仍使用了9%左右。通过jstack发现cpu最高的线程stack为Thread.sleep

此类问题相对来说更复杂一些,因为我们已经找到了相关的繁忙代码,但是这类代码不应该造成cpu繁忙。如read from console应该永远都不到,因为没有人输入; 如 thread.sleep不应该造成high cpu。

这里我给出一个思路

使用jvisualvm继续看一下,能否找到繁忙method的具体情况。可能在这一步就找到了问题根本原因

查看相关源代码

如:read lines from console这个例子,通过查看源代码可知,我们不期望从console读到任何东西,那么为什么读到了?读到了什么值? 可以通过重新编译源代码或者btrace注入的方式,看一下到底读到的什么值,进一步查看。那篇文章中,作者直接在console read之后,加入了一个sleep,简单粗暴的解决了这个问题。其实也没啥问题。

如:tomcat sleep的例子,通过检查源代码,

at java.lang.Thread.sleep(NativeMethod)

at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java: 1355)

at java.lang.Thread.run(Thread.java:748)

如果真正的在sleep,cpu肯定不会高。我怀疑下面的backgroundProcessorDelay值有问题。

while (!threadDone) {

try {

Thread.sleep(backgroundProcessorDelay * 1000L);

} catch (InterruptedException e) {

// Ignore

}

if (!threadDone) {

processChildren(ContainerBase.this);

}

}

这个可以通过btrace注入Thread.sleep方法,查看它到底调用的值是多少。

例子:查看哪个线程最繁忙(下面脚本可以直接复制粘贴到你的linux shell中)

直接复制下面的几行,就可以得到高cpu的那些线程,以及一个完整的jstack输出文件

process_id=YOUR_PROCESS_ID_TO_BE_REPLACED

tmp_jstack_file=/tmp/$(date '+%Y%m%d_%H%M%S')_$USER_$$_${process_id}_jstack_$RANDOM

jstack ${process_id} > $tmp_jstack_file

ps -Leo pid,lwp,user,comm,pcpu --no-headers| grep "^[[:space:]]\+${process_id}[[:space:]]\+" | sort -k5 -r -n | head -n"${top_count:-5}" | while read thread_line

do

threadI

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值