Java应用程序中的高CPU利用率 – 为什么?

我有一个Java应用程序(基于Web),有时显示非常高的CPU利用率(几乎90%)几个小时。 Linux TOP命令显示了这一点。 在应用程序重启时,问题就消失了。

所以要调查

我使用Thread Dump来查找线程正在做什么。 在'RUNNABLE'状态中找到了几个线程,其中一些在其他几个状态中。 在重复的线程转储中,我确实看到一些始终存在于'RUNNABLE'状态的线程。 所以,他们似乎是罪魁祸首。

但是我无法确定,哪个Thread正在占用CPU或进入无限循环(从而导致高CPU利用率)。

日志不一定有用,因为违规代码可能没有记录任何内容。

我如何调查 – 应用程序的哪个部分或什么线程导致高CPU利用率? – 还有其他想法吗?

如果分析器不适用于您的设置,您可以尝试在此post中的步骤之后识别该线程。

基本上,有三个步骤:

  1. 运行top -H并获取具有最高CPU的线程的PID。
  2. 将PID转换为hex。
  3. 在线程转储中查找具有匹配HEX PID的线程。

您可能是垃圾收集问题的受害者。

当您的应用程序需要内存并且它的配置使用时,垃圾收集器的运行频率会降低,这会占用大量的CPU周期。 如果它无法收集任何东西,你的记忆力会保持低水平,所以它会一次又一次地运行。 重新部署应用程序时,内存将被清除,垃圾收集不会超过所需的次数,因此CPU利用率会保持低水平,直到它再次满。

您应检查应用程序中是否存在可能的内存泄漏,并且已为内存配置良好(请查看-Xmx参数,请参阅Java选项-Xmx代表什么? )

另外,您使用什么作为Web框架? JSF依赖于会话并消耗大量内存,最多考虑无状态!

在这些峰值CPU时间内,用户负载如何? 你说这是一个基于Web的应用程序,所以想到的罪魁祸首就是内存利用率问题。 例如,如果你在会话中存储了很多东西,并且会话数量足够高,那么app服务器就会开始吵架。 这也是GC根据您使用的方案可能会使事情变得更糟的情况。 有关应用程序和服务器配置的更多信息将有助于指出更多的调试思路。

你的第一个方法应该是找到对Thread.sleep的所有引用并检查:

  1. 睡觉是正确的做法 – 如果可能的话,你应该使用某种等待机制 – 也许小心使用BlockingQueue会有所帮助。

  2. 如果睡觉正确的事情,你是否在适当的时间内睡觉 – 这通常是一个非常难以回答的问题。

multithreading设计中最常见的错误是相信在等待事情发生时你需要做的就是检查它并在紧密的循环中hibernate一会儿。 这很少是一种有效的解决方案 – 您应该始终尝试wait发生。

第二个最常见的问题是循环而不睡觉 。 这更糟糕,并且不容易追踪。

在线程转储中,您可以找到如下行号。

对于当前正在运行的主线程…

 "main" #1 prio=5 os_prio=0 tid=0x0000000002120800 nid=0x13f4 runnable [0x0000000001d9f000] java.lang.Thread.State: **RUNNABLE** at java.io.FileOutputStream.writeBytes(Native Method) at java.io.FileOutputStream.write(FileOutputStream.java:313) at com.rana.samples.**HighCPUUtilization.main(HighCPUUtilization.java:17)** 

您没有将“linux”分配给问题但是您提到了“Linux top”。 因此这可能会有所帮助:

使用小型Linux工具threadcpu来识别使用线程的最多cpu。 它调用jstack来获取线程名称。 通过管道中的“sort -n”,您可以获得按cpu使用情况排序的线程列表。

有关详细信息,请访问: http : //www.tuxad.com/blog/archives/2018/10/01/threadcpu_-_show_cpu_usage_of_threads/index.html

如果您仍需要更多详细信息,请在线程上创建线程转储或运行strace。