java进程占用CPU过高常见的两种情况及分析定位

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dingjianmin/article/details/85705812

java进程爆cpu的快速定位

1、背景

在程序开发的过程中,难免遇到进程占用cpu过高(现网居多、开发环境)的情况,现网出现这种情况就需要及时的能定位到问题,快速解决,否则就导致系统不可用,用户投诉等多种一系列的问题。

2、java进程占用CPU过高常见的两种情况:

  • 代码中有死循环或者接近死循环的操作
  • 快速创建大量临时变量,导致频繁触发gc回收

3、在windows中的定位方法

如图所示:

用jvisualvm 和 jconsole貌似都只能看到总共占用的cpu 看不到每个线程分别占用的cpu。

所以在windows平台上要找出到底是哪个线程占用的cpu还不那么容易,linux用top就行了。

3、定位步骤:

3.1、找到java进程对应的pid。

找pid的方法是:打开任务管理器,然后点击 “查看” 菜单,然后点击 “选择列”,把pid勾上,然后就可以在任务管理器里面看到所有进程的pid值了。
(也可以用第三步中提到的工具直接查看),在win10详细信息里面直接可以看到pid值。

3.2.然后把java进程导出快照。直接运行命令。


找到导出的文件打开d:/jstack182880.stack文件。

3.3、在windows下只能查看进程的cpu占用率,要查看线程的cpu占用率要借助其他的工具,这里用的是微软提供的 Process Explorer v15.3

下载地址:点击这里下载

下载完后解压运行

找到cpu占用高的线程,双击显示如图,或者右键点击需要查看的进程—properties

3.4.然后选择 Threads 选项卡,找到占用cpu的线程的tid,比如我这里是 224664 的线程

这里我们可以发现有多个线程占用7%左右,导致cpu占用较高

3.5.把pid转换成16进制,我这里直接用系统自带的计算器转换,置于为什么要转换,是因为先前用jstack导出的信息里面线程对应的tid是16进制的。

3.6.在 d:/jstack182880.stack文件中查找 36d98

找到相关代码,定位出问题所在。


4、在linux中的定位方法

4.1.找到CPU占用高的进程号 如:使用top命令查看(可以使用其它方法,只要找到对应的进程号即可)


注:图中第一列PID为进程号;

4.2、根据进程号找到CPU占用高的线程

如:使用命令top -H -p (其中要换成第一步找到的进程号)

注:图中第一列PID此时为线程号;

4.3.导出java进程执行堆栈,并找到对应的线程

使用jstack > jstack_xxx.txt (其中要换成第一步找到的进程号)
从第二步中的PID中找出一个CPU占用高的线程号,把它转成16进制,比如3261转成CBD
从导出的堆栈信息里找到nid为cbd的线程堆栈

4.4:从堆栈里找到对应的代码执行类和方法

若代码为业务代码,则需要具体分析代码,找出代码中死循环或接近死循环的地方,并修正;定位结束;

若堆栈信息为gc线程(类似下图),则需要进行下一步

4.5:dump出java进程的堆对象使用情况

使用jmap -histo > jmap_xxx.txt

找出量比较大的、且跟业务有关的对象,找到这些对象创建的地方进行分析;一般需要持续创建大量的对象,使得内存不够用时,才会频繁触发gc进行回收,gc回收时jvm有停顿,CPU也占用很高。

线程之间的切换,是很耗费性能的,所以带来CPU飙升.
新生代设置过小,也会频繁触发gc。有大对象始终根节点路径可达,无法释放,jvm在疯狂的Full GC。

展开阅读全文

没有更多推荐了,返回首页