您的位置:首页 > 编程语言 > Java开发

java进程导致CPU负载高

2016-08-01 22:03 274 查看
在工作中,经常会碰到由于代码问题导致的高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,如上面的241382)使用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<\0|0\6\305\6\1L\23\20\ttb1518437\1"..., 2011) = 2011
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java cpu