【问题标题】:The way to solve cpu load too high of Java applicationJava应用程序cpu负载过高的解决方法
【发布时间】:2015-10-10 01:39:51
【问题描述】:

今天发现我的服务器cpu负载太高,服务器只是运行一个Java应用。

这是我的操作步骤。

  1. 我使用top 命令来查找应用程序的 pid。 pid 为 25713。

  2. 我使用top -H -p 25713 命令找到了一些占用cpu 最多的pid。如25719 tomcat 20 0 10.6g 1.5g 13m R 97.8 4.7 314:35.22 java

  3. 我使用jstack -F 25713命令打印转储信息。如"Gang worker#4 (Parallel GC Threads)" os_prio=0 tid=0x00007f5f10021800 nid=0x6477 runnable

  4. 我从转储文件中搜索了 pid。然后发现占用cpu最多的pid都是"Gang worker#4 (Parallel GC Threads)" os_prio=0 tid=0x00007f5f10021800 nid=0x6477 runnable

  5. 我用jstack命令后cpu就正常了!

这是我的问题:

  1. 为什么GC Threads 使cpu 负载过高。
  2. 为什么我用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] 

【问题讨论】:

  • 对于 Java 7 来说,关闭并行 GC 就成功了:-XX:-UseParallelGC.
  • @rsutormin - Voodoo GC 调整 ....
  • 你使用什么操作系统、java版本和CPU?在您使用jstack -F 之前,我是否正确理解该进程一直停留在 GC 中?
  • @the8472,Linux version 2.6.32-504.el6.x86_64,32 Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz,jdk1.8.0_60.是的,我的应用程序恢复正常,直到我使用 jstack -F
  • 奇怪的是,如果是 futex_wait 错误导致它,关闭并行 GC 可能确实可行。

标签: java garbage-collection jstack


【解决方案1】:

只是猜测,您可能会受到某些内核版本中的futex_wait bug 的影响。

更一般地说,jstack -F 向进程发送一个信号,这将中断任何可能正在休眠的线程。所以也许 GC 线程只是在等待另一个以某种方式错过唤醒的线程。 IE。如果它确实卡在 GC 中并且发送信号修复了问题,那么这可能指向锁定或内存排序错误,如果不在内核中,那么在 JVM 中。

您可以尝试将SIGBREAK 发送到进程,而不是使用jstack -F,看看是否有相同的效果。

【讨论】:

  • 我如何将SIGBREAK 发送到进程。举个例子?
  • 服务器上还有其他java应用,但是都找到了..求帮助。
  • 对不起,我听不懂你在说什么。
  • 这不是系统错误。如果我将应用程序部署在其他服务器上,也有同样的问题..so .
  • 那么也许您应该看看服务器、JVM 版本或 JVM 标志 (-XX:+PrintFlagsFinal) 之间是否存在任何差异。或者,如果您的系统由于其他 JVM(交换、IO、CPU 负载)而出现负载峰值
【解决方案2】:

为什么 GC 线程会使 cpu 负载过高。

您的 JVM 可能正在运行完整的 GC。而且由于您的 JVM 可能正在运行一个巨大的堆(由 10.6 GB 的内存大小暗示),这将需要很长时间。您的系统也有可能正在颠簸虚拟内存。

为什么我使用 jstack 命令后 cpu 变得正常了。

巧合……大概。 GC 在您运行 jstack 时完成。


如果您想对此进行调查,我建议您打开垃圾收集日志记录,并尝试将高 CPU 负载时​​段与 GC 活动相关联。

GC 日志应该告诉您的另一件事是您的 Tomcat 堆是否太满。如果您的 webapps 有内存泄漏,那么这将导致堆填满无法被垃圾回收的对象。随着时间的推移,这将导致 JVM 花费越来越多的时间来运行 GC。如果这是问题所在,那么您需要找到并修复内存泄漏。

【讨论】:

  • 最后打印的GC日志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]
  • 这看起来不像是“满堆”/“内存泄漏”问题。但是,我不是 GC 调优专家。我建议您剪切粘贴更多的 GC 日志,并将您的 JVM 的 GC 切换到问题中......并希望其他人可以帮助您。
猜你喜欢
  • 2015-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-13
  • 2019-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多