如何找出垃圾回收器使用了90%的CPU?

3
我有一个Java程序,在运行20-30分钟后开始变得卡顿并使用过多的CPU,随着时间的推移情况越来越糟糕。
我使用的是Ubuntu Linux 17.10,使用Open JRE 8_151。我确认这个bug也会出现在Windows上,使用Oracle JRE 8_131(我认为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分钟才会开始出现。
这可能需要一段时间,所以我希望有更聪明的方法,就像我上面尝试的那样。
有什么建议吗?
附言:我从未在我的代码中调用System.gc()。
1个回答

2

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


我有大约6000个小但长寿的对象。我如何使用G1 GC指定它们? - Grumblesaurus
1
使用-XX:+UseG1GC - Hash Jang
我现在会尝试一下,然后告诉你进展如何。真的希望能够接受你的答案,谢谢! - Grumblesaurus
@JoshuaD 有帮助吗?我也遇到了同样的问题。 - Harshit Gupta
@Harshit Gupta 是的,这确实帮了很多。我还在Linux上使用了一个进程检查器来查看哪些线程在做什么。 - Grumblesaurus
@JoshuaD 我的 CPU 使用率仍然会慢慢地上升到 100%,并保持在那里,直到重新启动。 - Harshit Gupta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接