Log4j2:NoClassDefFoundError:静态嵌套类

时间:2014-09-15 23:37:12

标签: java log4j log4j2

我已经看到在升级到log4j2之后,它无法使用java.lang.NoClassDefFoundError加载静态嵌套类。

我有一个SingletonHolder这样的课程

class SingletonHolder {
  static class Holder {
    private static final SingletonInstance INSTANCE = new SingletonInstance();
  }

  static public SingletonInstance getInstance() {
    return INSTANCE;
  }
}

引用SingletonHolder.getInstance()时,我收到以下异常

Caused by: java.lang.NoClassDefFoundError: Could not initialize class mypkg. SingletonHolder$Holder
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:340)
        at org.apache.logging.log4j.core.util.Loader.initializeClass(Loader.java:285)
        at org.apache.logging.log4j.core.impl.ThrowableProxy.loadClass(ThrowableProxy.java:500)
        at org.apache.logging.log4j.core.impl.ThrowableProxy.toExtendedStackTrace(ThrowableProxy.java:621)
        at org.apache.logging.log4j.core.impl.ThrowableProxy.<init>(ThrowableProxy.java:170)
        at org.apache.logging.log4j.core.impl.ThrowableProxy.<init>(ThrowableProxy.java:171)
        at org.apache.logging.log4j.core.impl.ThrowableProxy.<init>(ThrowableProxy.java:148)
        at org.apache.logging.log4j.core.impl.Log4jLogEvent.getThrownProxy(Log4jLogEvent.java:323)
        at org.apache.logging.log4j.core.pattern.ExtendedThrowablePatternConverter.format(ExtendedThrowablePatternConverter.java:64)
        at org.apache.logging.log4j.core.pattern.PatternFormatter.format(PatternFormatter.java:36)
        at org.apache.logging.log4j.core.layout.PatternLayout.toSerializable(PatternLayout.java:189)
        at org.apache.logging.log4j.core.layout.PatternLayout.toSerializable(PatternLayout.java:53)
        at org.apache.logging.log4j.core.layout.AbstractStringLayout.toByteArray(AbstractStringLayout.java:52)
        at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:104)
        at org.apache.logging.log4j.core.appender.RollingFileAppender.append(RollingFileAppender.java:86)
        at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:97)
        at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:428)
        at org.apache.logging.log4j.core.async.AsyncLoggerConfig.asyncCallAppenders(AsyncLoggerConfig.java:118)
        at org.apache.logging.log4j.core.async.AsyncLoggerConfigHelper$Log4jEventWrapperHandler.onEvent(AsyncLoggerConfigHelper.java:222)
        at org.apache.logging.log4j.core.async.AsyncLoggerConfigHelper$Log4jEventWrapperHandler.onEvent(AsyncLoggerConfigHelper.java:207)
        at com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:128)

此代码在转移到log4j2之前工作正常。

我的log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error" name="app">
    <Appenders>
        <RollingFile name="RollingFile" fileName="app.log"
                     immediateFlush="false" filePattern=app.%d{yyyy-MM-dd}.%i.log">
            <PatternLayout pattern="%d{ISO8601} - ${sys:ISApplicationName} ${sys:appVersion} %-5p [%t:%C{1}:%L] - %msg%n"/>
            <Policies>
                <OnStartupTriggeringPolicy />
                <TimeBasedTriggeringPolicy />
            </Policies>
            <DefaultRolloverStrategy max="7"/>
        </RollingFile>
        <RollingFile name="RollingFileAccess" fileName="access.log"
                     immediateFlush="false" filePattern="access.%d{yyyy-MM-dd}.%i.log">
            <PatternLayout pattern="%d{ISO8601} ${sys:ISApplicationName}-${sys:appVersion} %msg%n"/>
            <Policies>
                <OnStartupTriggeringPolicy />
                <TimeBasedTriggeringPolicy />
            </Policies>
            <DefaultRolloverStrategy max="7"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <AsyncLogger name="accessLogger" level="info" additivity="false">
            <AppenderRef ref="RollingFileAccess"/>
        </AsyncLogger>
        <asyncRoot level="info" includeLocation="true" additivity="false">
            <AppenderRef ref="RollingFile"/>
        </asyncRoot>
    </Loggers>
</Configuration>

我使用以下属性启动应用程序

  -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector -Dlog4j.configurationFile="path_to/log4j2.xml"

1 个答案:

答案 0 :(得分:0)

不确定这是否有所不同,但我建议您使用Log4jContextSelector系统属性使所有记录器异步,或<AsyncRoot><AsyncLogger>配置元素,以便您可以混合异步记录器与正常记录器。我不建议你两者兼顾。因此,如果您使用Log4jContextSelector系统属性,请使用正常的<Root><Logger>配置元素进行配置。

我注意到错误消息在包名和类名之间有一个空格:"Could not initialize class mypkg. SingletonHolder$Holder" ...这对我来说很奇怪。这可能是代码中的错误吗?或者在这里写问题时这是一个复制粘贴的错误吗?

我试图重现这个问题,但我还需要更多细节。日志如何在这里发挥作用?您是否正在记录单身实例,如下所示?

logger.info("some message with singleton {}", SingletonHolder.instance());