在Java中,是什么导致了长时间的自旋和同步时间?

12

在Java 8更新45中,将这些选项添加到java调用中:

-XX:+PrintGCApplicationStoppedTime
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1

显示给我这样的统计数据:

vmop [threads: total initially_running wait_to_block] [time: spin block sync cleanup vmop] page_trap_count
3679.229: no vm operation [ 72 1 2 ] [ 6016 0 6016 0 0 ]  1
2015-05-22T11:25:27.519+0200: Total time for which application threads were stopped: 6.0168551 seconds, Stopping threads took: 6.0164099 seconds

问题在于“停止线程”的时间很长。在这个例子中,它已经达到了6秒,这对我们的应用程序来说已经是一个问题了,但我曾经看到过更长的时间,比如在某个实例中(虽然没有完整的日志记录),达到了将近一分钟。

VM操作(这里是 no vm operation )是不稳定的。我也见过其他操作,例如 RevokeBias G1IncCollectionPause GCG_Operation 。另外, page_trap_count 似乎不相关。我见过一些示例,其中它是0,而其他示例中它是2。不过,值得注意的是,这些时间值总是反映在 spin sync 的值中。

我正在寻找对这些时间值 spin sync 的深入解释,但我更感兴趣的是为什么会发生这种情况以及我可以采取什么措施。我不知道我们的配置中是否存在任何“恶意行为”。机器上有大量闲置的核心和未使用的内存,我们正在运行纯Java(没有JNI),并且我们不知道我们的代码中是否存在过度的同步。


你可以提供更多关于你特定使用情况的细节,这样人们就能知道如何帮助你。 - Eric
实际上,我不仅在我们的一个应用程序中看到了这个问题,而是在整个领域都看到了。因此,没有真正特定的用例。如果我知道要寻找什么,我可以去寻找相似之处。然而,我有点怀疑许多人都有同样的问题,但还没有注意到。指向它的日志“停止线程花费:”是相当新的。 - malamut
1个回答

4
问题在于你的应用程序需要很长时间才能到达安全点。 "Stopping threads" 输出表示 JVM 发出安全点请求直到所有线程到达安全点之间的时间。
"sync" 值显示相同的内容-它是所有线程到达安全点所需的时间。
"spin" 和 "block" 值表示 "blocked" 和 "spinning"(执行代码)线程到达安全点所需的时间。
了解这一点,我们可以得出结论,对于您来说问题在于一个线程正在忙于旋转而无法在几秒钟内到达其安全点。
确切地说,为什么会发生这种情况很难说。例如,如问题及其答案所示,JIT 编译器可以编译没有安全点检查的重型循环。
您可以尝试使用选项-XX:+SafepointTimeout -XX:SafepointTimeoutDelay=500运行 JVM。这将在 500 毫秒后超时安全点同步,并打印未能到达安全点的线程信息。

谢谢!我会尝试这个并回报。 - malamut
额外的选项确实可以给我线程名称(没有堆栈,但目前似乎没有办法获取它)。看看其中一个出现问题的应用程序,大部分时间线程都是相同的。看起来要找到实际问题需要做一些艰苦的工作,但我现在知道从哪里开始了,这个问题肯定已经得到解答了! - malamut
@malamut 现在你知道了线程,也许定期的线程转储(jstack <pid>)可以帮助解决问题。它们也会等待安全点,所以即使有这个帮助,可能仍然很难确定问题所在。一旦你确定了问题,我很想知道是什么问题。这是一个有趣的问题。 - K Erlandsson
我会汇报有趣的发现。遗憾的是,这不会很容易,因为可能有不止一个原因。我目前正在寻找的一个原因只与一个应用程序有关。当禁用JIT时,它就会消失,所以我将首先按照您提供的链接问题的轨迹进行跟踪。 - malamut
1
我找到了我们自己的一个方法,将其从编译中排除后,问题就解决了。我并不完全相信这个方法本身是问题所在;排除它可能只是掩盖了实际的问题。无论如何,我可以排除它,所以现在我只是这样做,并且不再提出更多问题。 :) 接下来要解决的是G1暂停时奇怪的长时间复制。不过这个问题还没有准备好在这里讨论。需要先进行一些额外的研究。 :) - malamut
@Zentopia 是的,定期休眠的线程不应该有问题。 - K Erlandsson

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