如何弄清楚为啥垃圾收集器使用了我 90% 的 CPU?

Posted

技术标签:

【中文标题】如何弄清楚为啥垃圾收集器使用了我 90% 的 CPU?【英文标题】:How to figure out why the garbage collector is using 90% of my CPU?如何弄清楚为什么垃圾收集器使用了我 90% 的 CPU? 【发布时间】:2017-12-28 03:30:43 【问题描述】:

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

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

我等了大约 45 分钟,直到程序使用了大量 CPU(大约 90%),并采取了以下操作来尝试识别我的程序中的哪个线程正在占用大量 CPU:

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% 的处理器能力来进行垃圾收集。

我该去哪里尝试调试这个问题?我可以开始禁用活动运行的线程以查看问题是否消失,但考虑到它

    不会在每次启动时都显示;和 需要 20-30 分钟才能开始显示

这可能需要一些时间,所以我希望有一些更聪明的东西,就像我上面尝试的那样。

有什么建议吗?

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

我愿意。我有大约 6000 个小但寿命长的物体。如何指定使用 G1 GC? 使用-XX:+UseG1GC 我现在就试一试,然后告诉你进展如何。真心希望能采纳你的回答,谢谢! @JoshuaD 有帮助吗?我也遇到了同样的问题。 @Harshit Gupta 是的,这很有帮助。我还在 linux 上使用了一个进程检查器来查看哪些线程在做什么。

以上是关于如何弄清楚为啥垃圾收集器使用了我 90% 的 CPU?的主要内容,如果未能解决你的问题,请参考以下文章

如何弄清楚为啥行从我的 SQL 服务器中消失了?

使用带有类的重载函数,无法弄清楚垃圾来自哪里

SCJP 想知道对象何时被垃圾收集的问题?

我如何弄清楚为啥这个多面体在雪花中无效?

使用 mypy 进行类型检查,我无法弄清楚为啥会发生此错误 [关闭]

为啥电脑进不了bios?