今天,我发现服务器的CPU负载过高,服务器只是在运行Java应用程序。
以下是我的操作步骤。
我使用top
命令查找应用程序的pid。 pid是25713。
我使用top -H -p 25713
命令查找了一些使用了大部分cpu的pid。例如25719 tomcat 20 0 10.6g 1.5g 13m R 97.8 4.7 314:35.22 java
。
我使用jstack -F 25713
命令打印转储信息。例如"Gang worker#4 (Parallel GC Threads)" os_prio=0 tid=0x00007f5f10021800 nid=0x6477 runnable
我从转储文件中搜索了pid。然后我发现使用大部分cpu的pid都像"Gang worker#4 (Parallel GC Threads)" os_prio=0 tid=0x00007f5f10021800 nid=0x6477 runnable
使用jstack
命令后,cpu变得正常了!
以下是我的问题:
GC Threads
使cpu负载过高。jstack
命令后,cpu变得正常。每次都超过这个时间。
以下是一些正常日志。2015-10-10T10:17:52.019+0800: 71128.973: [GC (Allocation Failure) 2015-10-10T10:17:52.019+0800: 71128.973: [ParNew: 309991K->206K(348416K), 0.0051145 secs] 616178K->306393K(1009920K), 0.0052406 secs] [Times: user=0.09 sys=0.00, real=0.01 secs]
当CPU过高时,GC日志保持在[GC (Allocation Failure) 2015-10-10T10:18:10.564+0800: 71147.518: [ParNew:
,并且没有其他日志。
执行jstack
命令时,打印日志
2015-10-10T10:17:50.757+0800: 53501.137: [GC (Allocation Failure) 2015-10-10T10:17:50.757+0800: 53501.137: [ParNew: 210022K->245K(235968K), 369.6907808 secs] 400188K->1
90410K(1022400K), 369.6909604 secs] [Times: user=3475.15 sys=11.69, real=369.63 secs]
答案 0 :(得分:4)
猜测,可能会受某些内核版本中的futex_wait bug影响。
更一般地说,java.time
向进程发送一个信号,该信号将中断任何可能正在休眠的线程。所以也许GC线程只是旋转等待另一个错误唤醒的线程。即如果它确实卡在GC中并且发送信号修复了问题,那么这可能指向锁定或内存排序错误,如果不在内核然后在JVM中。
您可以尝试将jstack -F
发送到流程,看看是否有相同的效果,而不是使用jstack -F
。
答案 1 :(得分:0)
为什么GC线程使CPU负载过高。
您的JVM可能正在运行完整的GC。而且由于你的JVM可能运行的是一个巨大的堆(以10.6 GB的内存大小暗示),这需要很长时间。您的系统也可能会破坏虚拟内存。
为什么我使用jstack命令后cpu变得正常。
巧合......可能。运行jstack时GC已完成。
如果您想对此进行调查,我建议您打开垃圾收集日志记录,并尝试将高CPU负载的周期与GC活动相关联。
GC日志应该告诉你的另一件事是你的Tomcat堆是否太满了。如果您的webapps有内存泄漏,那么这将导致堆填满无法收集垃圾的对象。随着时间的推移,这将导致JVM花费越来越多的时间来运行GC。如果这是问题所在,那么您需要找到并修复内存泄漏。