【问题标题】:Execution blocks because of using System.out.println() in logging inside a for loop?由于在 for 循环内使用 System.out.println() 记录而导致执行块?
【发布时间】:2016-03-15 03:46:09
【问题描述】:

今天我们在 JBoss EAP alpha 版本的 Java EE 项目中遇到执行被阻塞(“阻塞” - 这应该是更专业的词,但此时我无法弄清楚)的情况,一段时间后没有更多控制台消息。

最后我们发现我的一个同事错误地将 System.out.println() 用于记录在 for 循环中,而不是 slf4j 记录器(循环迭代数百次)。

slf4j 记录器的 log.xxxxx() 替换 System.out.println() 后一切正常

我无法理解System.out.println() 的这个奇怪问题。 此外,应用程序服务器正在运行,但无法处理任何请求。

谁能帮我理解这个问题以及为什么 JBoss 无法处理其他请求。

【问题讨论】:

  • 您是否能够重现该错误,即把它放回System.out.println() 看看会发生什么。
  • 是的,从 sysout 替换 slf4j 记录器同样痛苦。我们挣扎了 2-3 个小时才发现问题。
  • 您是否尝试附加远程调试器以确认您卡在该行上?
  • 不,因为情况不允许我从 Eclipse 进行调试。我必须在 jboss 中部署战争。
  • 即使您的 Web 应用程序未在“在 Eclipse 中”运行,您仍然可以“从”Eclipse 调试。您将其部署到 JBOSS 并附加 remote 调试器。查看 Eclipse - JBOSS 远程调试说明

标签: java jakarta-ee logging system.out


【解决方案1】:

JBoss remapps the System.err 带有将其输出重定向到日志记录的 PrintStream。我想你在记录器锁和流锁之间是running into a deadlock

  • Thread 1 执行 logger.log->(锁定 logger)->Console Appender->System.err(锁定流)
  • Thread 2 执行 System.err.println->(锁定流)->logger.log->(锁定记录器)。

如您所见,每个线程都以相反的顺序获取锁。

你说不可能! org.jboss.logging.util.LoggerStream 的源代码根本没有任何同步关键字。如果 LoggerStream 没有抢到锁,它怎么会死锁?

很简单,他们没有覆盖java.io.PrintStream 中声明的每个方法。所以如果你调用 System.err.println(int) 或 System.err.println(boolean) 你就有麻烦了。

【讨论】:

    最近更新 更多