在一个基于Swing / Spring的大型应用程序中,我们看到了以下异常。此错误发生在用户交互过程中,用户交互触发Spring通过commons warn(String, Throwable)报告警告,而后者又调用log4j。不幸的是,我无法将此问题分解为一个独立的示例。
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/apache/log4j/spi/ThrowableInformation
at org.apache.log4j.spi.LoggingEvent.<init>(LoggingEvent.java:165)
at org.apache.log4j.Category.forcedLog(Category.java:391)
at org.apache.log4j.Category.log(Category.java:856)
at org.apache.commons.logging.impl.Log4JLogger.warn(Log4JLogger.java:234)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:487)
<company specific code>
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:749)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:702)
at java.awt.EventQueue$3.run(EventQueue.java:696)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:719)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.spi.ThrowableInformation
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 27 more环境
观察/我尝试过的东西
System.getProperty("java.class.path")手动打印类路径以验证log4j JAR是否存在-是的,只有一个版本出现在1.2.17static void main()中,则正确加载log4j类,并在控制台中看到警告,以后不会出现异常。<==这证实了log4j JAR在应用程序中是可见的,假设没有多个类加载器.代码
Log logger = LogFactory.getLog(getClass());
logger.warn("foo", new Exception());代码
380 if (result == null) {
381 throw new ClassNotFoundException(name); // <=== here
382 }
383 return result;例如
[Loaded org.apache.log4j.Category from file:/<path redacted>/log5j-1.2.17.jar]
[Loaded org.apache.log4j.Logger from file:/<path redacted>/log5j-1.2.17.jar]
[Loaded org.apache.log4j.Priority from file:/<path redacted>/log5j-1.2.17.jar]
我的理论
我的问题
发布于 2015-08-14 12:55:58
根本原因
URLClassLoader已经关闭,这对Java产生了不幸的影响。
背景
为了支持使用OSGI/ spring的应用程序的早期版本,我们在spring中使用了bean,允许从正确的包中加载资源,这是一个可怕的攻击,但在给定的代码、资源和XML文件中,唯一可以做到的方法是在不同的包中.
<bean id="classLoader" class="org.example.internal.PluginModuleClassLoader" factory-method="getClassLoader" />
<bean id="imageLoader" class="org.example.ImageLoader">
<property name="classLoader" ref="classLoader" />
</bean>
public class PluginModuleClassLoader {
public static ClassLoader getClassLoader() {
return PluginModuleClassLoader.class.getClassLoader();
}
}6个月前,我们将Spring从(2.5.5 )升级到4.1.2,并删除了OSGI,因为它没有任何好处,但是,由于从60+包中删除它的成本,现在遗留的60+机制仍然存在。
它是如何被关闭的
用户交互关闭一个应用程序上下文并加载另一个应用程序上下文.这有破坏应用程序上下文的副作用。春天会自动摧毁所有的豆子。在classLoader bean的情况下,它调用自动查找close()方法,即URLClassLoader.close(),这意味着所有后续的外观都会在ClassNotFoundException中失败
https://stackoverflow.com/questions/31991224
复制相似问题