2

我们的 Java(Web)应用程序在 JBoss 6x 中运行。当报告缓慢时:

  1. 线程堆栈转储被采取(详情如下)
  2. 检查内存 - 发现内存使用率非常高,几乎接近最大允许堆大小,但没有内存不足。

线程堆栈转储显示大多数线程在日志记录中被这些类型的错误阻塞:

waiting for monitor entry [0x000000004b6be000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at org.jboss.logmanager.handlers.WriterHandler.doPublish(WriterHandler.java:59)
    - waiting to lock <0x00002aaac9a2de68> (a java.lang.Object)
    at org.jboss.logmanager.ExtHandler.publish(ExtHandler.java:64)

像这样:

   java.lang.Thread.State: BLOCKED (on object monitor)
    at java.io.PrintStream.println(PrintStream.java:756)
- waiting to lock <0x00002aaac9817a08> (a com.whatever.SomeClass)
at com.something.ThatClass.thatMethod(ThatClass.java:169)

com.whatever.SomeClass 使用 org.apache.log4j.Logger
我们使用 Log4j 进行日志记录。

似乎线程在某些日志记录操作上都被阻塞了。这个问题过去也发生过,而且似乎是随机的,它会减慢/停止应用程序。

有任何想法吗?

4

1 回答 1

3

Jasper,所有日志框架都有一个同步块,它们将数据写入磁盘。这是为了防止在超过 1 个线程写入日志时出现乱码(您发布了一个示例 - 上的 BLOCKED 线程java.io.PrintStream.println)。

但是有一个解决方案,就是使用异步 appender。在工作中,我们有一些高吞吐量/低延迟的应用程序,我们必须对其进行配置以防止线程争用。

使用异步附加程序时需要考虑的一件事是,如果您的应用程序崩溃或被强制终止,您将不会在日志中看到最后的日志记录语句,因为它们可能没有写入磁盘.

于 2013-02-07T08:46:18.037 回答