2013-02-07 99 views
1

我們的Java(Web)應用程序在JBoss 6x中運行。 當緩慢報道:記錄器上阻塞的Java線程

  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進行日誌記錄。

看來線程在某些日誌記錄操作中都被阻塞。 過去也發生過這個問題,並且似乎是隨機的,並且會減慢/停止應用程序。

任何想法?

+0

可能在.log文件的任何文件操作並行 – TheWhiteRabbit

+0

正在發生也注意到,最近對RollingFileAppender進行中的log4j.xml,MaxBackupIndex大小已設置爲1000(MAXFILESIZE爲5MB)。 MaxBackupIndex的這麼高的值是否會成爲這個問題的原因? - – Jasper

回答

2

Jasper,所有日誌記錄框架都有一個同步塊,在這裏它們將數據寫入磁盤。這是爲了防止當多於一個線程寫入日誌時發生日誌篡改(您發佈了一個示例 - java.io.PrintStream.println上的BLOCKED線程)。

但有一種解決方案,即使用asynchronous appender。在工作中,我們有一些高吞吐量/低延遲的應用程序,我們必須配置它來防止線程爭用。

當你使用異步appender時,你需要考慮的一件事是,如果你的應用程序崩潰或被強制終止,你將不會在日誌中看到最後一條日誌語句,因爲它們可能不是'寫入磁盤。

+1

關於AsyncAppender問題,請參閱http://stackoverflow.com/a/13144054/603516,並提供進一步減少爭用的提示。 – Vadzim

+0

大多數日誌記錄框架都具有sychronized塊,其中日誌條目排隊到日誌寫入線程。鎖定完整的磁盤寫入操作將非常困難。 –

+0

Martin,只有在使用Async appender時纔是如此。如果您使用正常的文件或控制檯appender,則日誌記錄框架將同步阻止任何其他日誌記錄操作。這就是爲什麼有一個異步appender,它反過來纏繞另一個appender。 – Augusto