Log4J blocked 问题

链接转载:http://www.cnblogs.com/suxuan/p/5041420.html

"qtp1056944384-232" prio=10 tid=0x00007f54900d0800 nid=0x63b3 waiting for monitor entry [0x00007f54492d0000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at org.apache.log4j.Category.callAppenders(Category.java:205)
	- waiting to lock <0x00000007e81c4830> (a org.apache.log4j.spi.RootLogger)
	at org.apache.log4j.Category.forcedLog(Category.java:391)
	at org.apache.log4j.Category.log(Category.java:856)
	at org.slf4j.impl.Log4jLoggerAdapter.info(Log4jLoggerAdapter.java:368)

 总计有200多个log4j的线程在等待锁"0x00000007e81c4830",而这把锁被谁持有呢?通过搜索,找到以下dump信息:

"qtp1056944384-218" prio=10 tid=0x00007f54800bb800 nid=0x63a5 runnable [0x00007f544a0de000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketOutputStream.socketWrite0(Native Method)
	at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
	at java.net.SocketOutputStream.write(SocketOutputStream.java:141)
	at net.logstash.log4j.SocketAppender.append(SocketAppender.java:190)
	at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
	- locked <0x00000007e8210868> (a net.logstash.log4j.SocketAppender)
	at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
	at org.apache.log4j.Category.callAppenders(Category.java:206)
	- locked <0x00000007e81c4830> (a org.apache.log4j.spi.RootLogger)
	at org.apache.log4j.Category.forcedLog(Category.java:391)
	at org.apache.log4j.Category.log(Category.java:856)
	at org.slf4j.impl.Log4jLoggerAdapter.info(Log4jLoggerAdapter.java:368)

为什么log4j会出现几百个线程等待一个锁的问题呢?log4j的Category.callAppenders源码:

  /**
     Call the appenders in the hierrachy starting at
     <code>this</code>.  If no appenders could be found, emit a
     warning.

     <p>This method calls all the appenders inherited from the
     hierarchy circumventing any evaluation of whether to log or not
     to log the particular log request.

     @param event the event to log.  */
public void callAppenders(LoggingEvent event) {
    int writes = 0;

    for(Category c = this; c != null; c=c.parent) {
      // Protected against simultaneous call to addAppender, removeAppender,...
      synchronized(c) {
        if(c.aai != null) {
            writes += c.aai.appendLoopOnAppenders(event);
        }
        if(!c.additive) {
            break;
        }
      }
    }

    if(writes == 0) {
      repository.emitNoAppenderWarning(this);
    }
  }

og4j版本1.x中,使用的是古老的synchronized(this),所有线程共用一个Category,而它通过log4j.properties指定。 同一个Category下的线程打log时,需要进行全局同步,因此它的效率会很低,log4j 1.x版不适合高并发的场景。

为了杜绝这样的问题,后续需要吸取教训:

1. 尽量减少不必要的日志,在成熟的接口上,关闭日志输出,这样有利于提高效率。

2. 替换底层log的实现类,不再使用log4j 1.x,使用logback(推荐)或者新的log4j 2.x版本。

最后,附带两篇关于log4j 1.x中,日志系统死锁的分析(我们最开始怀疑是这个问题):

https://bz.apache.org/bugzilla/show_bug.cgi?id=50213

http://javaeesupportpatterns.blogspot.com/2012/09/log4j-thread-deadlock-case-study.html


---------------
slf4j jar sources 下载: http://www.slf4j.org/download.html
log4j jar sources 下载: http://archive.apache.org/dist/logging/log4j/2.7/
log4j2 配置:
   http://www.cnblogs.com/morvenhuang/p/3958086.html
   官方配置:http://logging.apache.org/log4j/2.x/manual/configuration.html#AutomaticConfiguration
 
 
log4j和log4j2 分别配置http://josh-persistence.iteye.com/blog/2205021

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值