java 进程100_java 进程 cpu100%问题排查

1:前言

cpu是时分(time division)的,操作系统里有很多线程,每个线程的运行时间由cpu决定,cpu会分给每个线程一个时间片,时间片是一个很短的时间长度,如果在时间片内,线程一直占有,则是100%;我们应该意识到,cpu运行速度很快(主频非常高),除非密集型耗费cpu的运算,其它类型任务都会在小于时间片的时间内结束。

java cpu100%的排查步骤,基本都是一模一样的,只是命令稍有区别!

查找消耗cpu最高的进程PID

根据PID查出消耗cpu最高的线程号

根据线程号查出对应的java线程,进行处理。

2:Demo模拟

构造一个请求接口,模拟无限产生Person实例。

并进行接口调用:http://172.20.200.250:9563/demoService/demo/test?justDo=true

package com.nobody.controller;

import java.util.ArrayList;

import java.util.List;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.RestController;

import com.nobody.domain.Person;

@RestController

@RequestMapping("demo")

public class DemoController {

@GetMapping("test")

public boolean test(@RequestParam boolean justDo) {

List persons = new ArrayList<>();

int i = 1;

if (justDo) {

while (true) {

persons.add(new Person("张三", i));

System.out.println(persons.size());

}

}

return justDo;

}

}

3:排查过程

3.1:使用top命令找出cpu占用最高的进程

f81ec453488ebff8e1f1c1220d0aefa3.png

3.2:使用ps -ef | grep java或者jps命令查看cpu占用高的进程是否为java进程

0bd442f2906f247f8ce437025db2b54c.png

1eac837f9477a0488a3b06b75b2cc97f.png

3.3:使用top -H -p pid命令查询此进程的所有线程情况,发现主要有三个线程(PID为29871 29872 29873)占用cup高。

-H表示以线程的维度展示,默认以进程维度展示。

029a77eef6b6149dc505d08fe34a41bd.png

3.4:使用命令jstack pid > pid.tdump将此进程的线程栈导出到文件并使用cat命令进行查看。

pid.tdump文件后缀名随意,通常以tdump结尾。

jstack 29869 > 29869.tdump

cat 29869.tdump

3.5:将前一步骤查出的3个线程PID从十进制转为十六进制,因为java线程栈文件中的线程id是十六进制。对应分别为 29871 -> 0x74af,,29872 -> 0x74b0,29873 -> 0x74b1。

发现此3个线程中有2个为gc线程和1个工作线程。gc线程忙碌表示内存不够用了,要进行内存回收,可能是java内存回收不了,导致一直gc。

f068a87fc075d8e21cdbb3e77c56826d.png

3.6:使用jstat -gcutil pid命令查看进程的堆情况,发现年轻代中Eden(伊甸园)和old代已使用的占当前容量百分比很高,并且GC频繁。

2b0461dfd1ed1077ee88ce730b173f13.png

S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比

S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比

E:年轻代中Eden(伊甸园)已使用的占当前容量百分比

O:old代已使用的占当前容量百分比

M:元数据区使用比例

CCS:压缩使用比例

YGC:从应用程序启动到采样时年轻代中gc次数

YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)

FGC:从应用程序启动到采样时old代(全gc)gc次数

FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)

GCT:从应用程序启动到采样时gc用的总时间(s)

3.7:使用jmap -dump:live,format=b,file=pid.hprof pid命令导出堆文件,只导出live的对象。文件后缀名可以是任意的,因为它也是二进制的,不过通常以hprof结尾。

d7dddc1d7400e740b33fa340bcebac01.png

3.8:使用JAVA_HOME/bin/jvisualvm.exe工具分析快照。

载入快照(文件----->载入—>文件类型(堆))

c45cd08e87a1e44a5f14c46c5803a0c1.png

选择类列表,按照大小排序,找出占用内存最大的类别,发现是Person类。

b437130d57292a9337140f96058d348c.png

至此,问题找到原因,原来是在死循环中,不断生产Person实例,并且无法回收,不仅工作线程一直占用cpu,而且导致gc线程忙碌进行回收内存,但是回收不了,最后导致内存不足java.lang.OutOfMemoryError。

3fa91db9c0b943a28201d80888d97f0e.png

java的bin目录下有很多JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof。

本文同步分享在 博客“Μr.ηobοdy”(CSDN)。

如有侵权,请联系 support@oschina.cn 删除。

本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值