如何弄清楚为什么垃圾收集器使用90%的CPU?

时间:2017-12-28 03:30:44

标签: java debugging

我有一个java程序,在运行大约20-30分钟后开始变得迟钝并使用太多CPU,并且随着时间的推移继续变得更糟。

我使用Open JRE 8_151在Ubuntu Linux 17.10上。我确认在使用Oracle JRE 8_131的Windows上也会出现此错误(我假设为8_151)。

我等了大约45分钟,直到程序使用了大量的CPU(大约90%)并采取了以下行动来尝试识别我的程序中哪个线程是一个猪:

ps aux 
#Visually confirm the process is using 90% and note ID -- 20316

top -p20316 
#confirm usage, in top it says 366.3%; 4-core processor so this makes sense

[while in top] press shift + H
# See four threads each using about 85%
  20318
  20319
  20320
  20321

# Convert those to hex
  20318 -> 0x4f5e
  20319 -> 0x4f5f
  20320 -> 0x4f60
  20321 -> 0x4f61

[Exit top]

jstack -l 20316 | less  
[press / and search for those hex thread ids]

# Get the following results: 
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007ff9f8020000 nid=0x4f5e runnable 
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007ff9f8021800 nid=0x4f5f runnable 
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007ff9f8023800 nid=0x4f60 runnable 
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007ff9f8025000 nid=0x4f61 runnable   

所以垃圾收集器正在耗尽我的CPU。这对我来说不是很有帮助,因为我不知道哪个线程正在生成正在收集的对象,或者为什么它消耗了85%的处理器能力来进行垃圾收集。

我从哪里开始尝试调试此问题?我可以开始禁用活动的运行线程,以查看问题是否消失,但鉴于它

  1. 每次发布​​都没有表现出来;和
  2. 开始出现需要20-30分钟
  3. 这可能需要一段时间,所以我希望有一些更聪明的东西,就像我上面尝试过的那样。

    有什么建议吗?

    P.S。我从不在我的代码中调用System.gc()。

1 个答案:

答案 0 :(得分:2)

检查是否有大量长寿命对象。对于有几代人的垃圾收集器来说,这是一个致命的案例。在这种情况下,请尝试使用G1 GC。