java 启动负载高_java进程导致CPU负载高

在工作中,经常会碰到由于代码问题导致的高CPU耗用以及内存溢出问题...

发生这种问题首要就是找出占用消耗高资源的线程ID,再利用strace命令查看该线程所有的系统调用

实际工作故障案例:

一台gateway告警,CPU资源利用率一直保持100%,且居高不下

1)利用top查看可疑进程PID

top - 09:37:18 up 70 days, 16:29,  2 users,  load average: 1.13, 1.04, 0.97

Tasks: 105 total,   1 running, 104 sleeping,   0 stopped,   0 zombie

Cpu(s):  1.0%us,  4.9%sy,  0.0%ni, 93.6%id,  0.0%wa,  0.0%hi,  0.0%si,  0.5%st

Mem:   2067816k total,  1756680k used,   311136k free,   236340k buffers

Swap:   524284k total,   255508k used,   268776k free,   277040k cached

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND

24138 apache    20   0 1273m 384m 3668 S 103.3 19.0   1232:39 java #java进程累计占用CPU103%

3359 root      39  19  2704   36    0 S  0.3  0.0   4:39.34 gam_server

6696 root      20   0 34148 1604  244 S  0.3  0.1   5:06.63 httpd

19254 root      20   0  785m 221m 3176 S  0.3 11.0   9:04.36 java

1 root      20   0  2224   28    0 S  0.0  0.0   1:22.46 init

2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd

3 root      20   0     0    0    0 S  0.0  0.0   0:33.42 ksoftirqd/0

5 root      20   0     0    0    0 S  0.0  0.0   0:00.03 kworker/u:0

也可以直接用top -H直接过滤系统中高消耗线程ID,如上面的24138

2)使用gstack命令查看进程中各线程的函数调用栈

gstack 24138 > gstack.log

在gstack.log中查找线程ID24138,由于函数栈会暴露函数细节,因此只显示了两个函数桢,线程ID24138对应线程号是37

Thread 37 (Thread 0x4696ab90 (LWP 24138)):

#0  0x40000410 in __kernel_vsyscall ()

#1  0x40241f33 in poll () from /lib/i686/nosegneg/libc.so.6

3)使用gcore命令转存进程映像及内存上下文

#gcore 24138

#该命令生成core文件core.24138

4)查看线程所有的系统调用

strace -p 29679

read(114, "\0\225\0\0\6\0\0\0\0\0\10\0\0\4\3\0\0\0p\365\1_\0\0\0\0\0\0\0\0\0\4"..., 2064) = 149

write(114, "\7\333\0\0\6\0\0\0\0\0\3\201r\4\0\0\0\0\0\0\0 B\25\274\252*\0\0\275.\0"..., 2011) = 2011

write(114, "\7\333\0\0\6\0\0\0\0\0Adddddc\2\301!\4\302dQQ\3\300R\37\3\300c"..., 2011) = 2011

write(114, "\7\333\0\0\6\0\0\0\0\0000\6\305\6\1JdK\ttb1521841\0010\1\200"..., 2011) = 2011

write(114, "\7\333\0\0\6\0\0\0\0\0000\6\305\6\1K6\27\ttb1533113\0010\1\200"..., 2011) = 2011

write(114, "\7\333\0\0\6\0\0\0\0\0

write(114, "\7\333\0\0\6\0\0\0\0\0\0010\1\200\1\200\2\301)\1\200\2\301\2\1\200\1\200\1\200\1\200"..., 2011) = 2011

write(114, "\0\34\0\0\6\0\0\0\0\0\200\1\200\1\200\1\200\n\300\31\20F\10\27#\23\23)", 28) = 28

read(114, "\0\225\0\0\6\0\0\0\0\0\10\0\0\4\3\0\0\0q\365\1_\0\0\0\0\0\0\0\0\0\4"..., 2064) = 149

write(114, "\7\333\0\0\6\0\0\0\0\0\3\201s\4\0\0\0\0\0\0\0 B\25\274\252*\0\0\311.\0"..., 2011) = 2011

发现有大量的写操作

5)用gdb调试core文件,并线程切换到37号线程

gcore和实际的core dump时产生的core文件几乎一样,只是不能用gdb进行某些动态调试

(gdb) gdb gateway core.24138

(gdb) thread 37

[Switching to thread 37 (Thread 0x4696ab90 (LWP 14086))]#0  0x40000410 in __kernel_vsyscall ()

(gdb) where

#0  0x40000410 in __kernel_vsyscall ()

#1  0x40241f33 in poll () from /lib/i686/nosegneg/libc.so.6

3)将需要分析的线程ID转换成16进制

printf "%x\n" 29679

73ef

4)最后打印线程的堆栈信息供开发一起分析调试源代码

jstack 29679|grep 73ef -A 30

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值