在重新部署时使用Janino + Logback + Tomcat的sun.reflect.MethodAccessorImpl的ClassNotFoundException

时间:2018-07-30 19:02:54

标签: tomcat logback slf4j janino

我有一个使用最新的logback 1.2.3,janino 3.0.8和slf4f 1.7.25在tomcat 8.5.32(最新的Java 8,1.8.0_181)下部署的应用程序。

我的logback xml具有如下过滤器:

<filter class="ch.qos.logback.core.filter.EvaluatorFilter">   
<evaluator> 
        <expression>return message != null &amp;&amp; message.contains("127.0.0.1");
</expression>   
</evaluator>   
<OnMismatch>NEUTRAL</OnMismatch>   
<OnMatch>DENY</OnMatch>
</filter>

一切正常,直到我重新部署为止。然后我得到这样的异常:

Jul 30, 2018 8:00:18 AM org.apache.catalina.startup.HostConfig reload
WARNING: Error during context [] restart
org.apache.catalina.LifecycleException: Failed to stop component [StandardEngine[Catalina-b].StandardHost[localhost].StandardContext[]]
        at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:238)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:142)
        at org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1386)
        at org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1287)
        at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1586)
        at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:280)
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:94)
        at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1136)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1372)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1376)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1344)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoClassDefFoundError: sun/reflect/MethodAccessorImpl
        at sun.misc.Unsafe.defineClass(Native Method)
        at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:63)
        at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:399)
        at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:394)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:393)
        at sun.reflect.MethodAccessorGenerator.generateMethod(MethodAccessorGenerator.java:75)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:53)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.codehaus.janino.ScriptEvaluator.evaluate(ScriptEvaluator.java:756)
        at org.codehaus.janino.ScriptEvaluator.evaluate(ScriptEvaluator.java:748)
        at ch.qos.logback.core.boolex.JaninoEventEvaluatorBase.evaluate(JaninoEventEvaluatorBase.java:72)
        at ch.qos.logback.core.filter.EvaluatorFilter.decide(EvaluatorFilter.java:65)
        at ch.qos.logback.core.spi.FilterAttachableImpl.getFilterChainDecision(FilterAttachableImpl.java:52)
        at ch.qos.logback.core.AppenderBase.getFilterChainDecision(AppenderBase.java:134)
        at ch.qos.logback.core.AppenderBase.doAppend(AppenderBase.java:80)
        at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:48)
        at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:272)
        at ch.qos.logback.classic.Logger.callAppenders(Logger.java:259)
        at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:441)
        at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:395)
        at ch.qos.logback.classic.Logger.log(Logger.java:787)
        at org.slf4j.bridge.SLF4JBridgeHandler.callLocationAwareLogger(SLF4JBridgeHandler.java:224)
        at org.slf4j.bridge.SLF4JBridgeHandler.publish(SLF4JBridgeHandler.java:301)
        at java.util.logging.Logger.log(Logger.java:738)
        at java.util.logging.Logger.doLog(Logger.java:765)
        at java.util.logging.Logger.logp(Logger.java:1042)
        at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:181)
        at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:147)
        at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4780)
        at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5411)
        at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
        ... 11 more
Caused by: java.lang.ClassNotFoundException: sun.reflect.MethodAccessorImpl
        at org.codehaus.janino.ByteArrayClassLoader.findClass(ByteArrayClassLoader.java:68)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 44 more

我的理论是juli-> SLF4J-> logback-> janino最终使用了容器类加载器,该容器类加载器最终停止了,但是日志记录框架没有意识到这一点。

关于如何解决此问题的任何想法?

1 个答案:

答案 0 :(得分:1)

事实证明这是由于logback监听器不在我的web.xml中引起的问题

ViewDidLoad

https://logback.qos.ch/manual/loggingSeparation.html明确指出:

  

大多数容器在以下位置调用侦听器的contextInitialized()方法   声明它们但调用它们的顺序   contextDestroyed()方法的顺序相反。因此,如果您   您的web.xml中有多个ServletContextListener声明,   然后应先声明ContextDetachingSCL,以便其   在应用程序关闭期间最后调用contextDestroyed()方法。