- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 Java Web 应用程序(使用 Spring),使用 Jetty 部署。如果我尝试在 Windows 计算机上运行它,一切都会按预期运行,但如果我尝试在 Linux 计算机上运行相同的代码,则会失败:
[normal startup output]11:16:39.657 INFO [main] org.mortbay.jetty.servlet.ServletHandler$Context.log>(ServletHandler.java:1145) >16> Set web app root system property: 'webapp.root' = [/path/to/working/dir]java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.mortbay.start.Main.invokeMain(Main.java:151) at org.mortbay.start.Main.start(Main.java:476) at org.mortbay.start.Main.main(Main.java:94)Caused by: java.lang.ExceptionInInitializerError at org.springframework.web.util.Log4jWebConfigurer.initLogging(Log4jWebConfigurer.java:129) at org.springframework.web.util.Log4jConfigListener.contextInitialized(Log4jConfigListener.java:51) at org.mortbay.jetty.servlet.WebApplicationContext.doStart(WebApplicationContext.java:495) at org.mortbay.util.Container.start(Container.java:72) at org.mortbay.http.HttpServer.doStart(HttpServer.java:708) at org.mortbay.util.Container.start(Container.java:72) at org.mortbay.jetty.Server.main(Server.java:460) ... 7 moreCaused by: org.apache.commons.logging.LogConfigurationException: org.apache.commons.logging.LogConfigurationException: No suitable Log constructor [Ljava.lang.Class;@15311bd for org.apache.commons.logging.impl.Log4JLogger (Caused by java.lang.NoClassDefFoundError: org/apache/log4j/Category) (Caused by org.apache.commons.logging.LogConfigurationException: No suitable Log constructor [Ljava.lang.Class;@15311bd for org.apache.commons.logging.impl.Log4JLogger (Caused by java.lang.NoClassDefFoundError: org/apache/log4j/Category)) at org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:543) at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:235) at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:209) at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:351) at org.springframework.util.SystemPropertyUtils.(SystemPropertyUtils.java:42) ... 14 moreCaused by: org.apache.commons.logging.LogConfigurationException: No suitable Log constructor [Ljava.lang.Class;@15311bd for org.apache.commons.logging.impl.Log4JLogger (Caused by java.lang.NoClassDefFoundError: org/apache/log4j/Category) at org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor(LogFactoryImpl.java:413) at org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:529) ... 18 moreCaused by: java.lang.NoClassDefFoundError: org/apache/log4j/Category at java.lang.Class.getDeclaredConstructors0(Native Method) at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389) at java.lang.Class.getConstructor0(Class.java:2699) at java.lang.Class.getConstructor(Class.java:1657) at org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor(LogFactoryImpl.java:410) ... 19 moreCaused by: java.lang.ClassNotFoundException: org.apache.log4j.Category at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) ... 24 more[shutdown output]
我已经使用 java -verbose:class
运行该应用程序,根据该输出,org.apache.log4j.Category 是从我的/WEB-INF/lib 中的 log4j JAR 加载的,就在第一个异常抛出之前。
现在,两台机器上的Java版本略有不同。两台机器都有Sun的java,Linux机器有1.6.0_10,而Windows机器有1.6.0_08,或者可能是07或06,我现在不记得确切的数字,而且手头没有机器。但即使 Java 的次要版本略有不同,代码也不应该像这样被破坏。有人明白这里出了什么问题吗?
最佳答案
您必须明白类加载器无法看到所有内容;他们只能看到父类加载器已加载的内容或他们自己加载的内容。因此,如果您有两个类加载器,比如说一个用于 Jetty,另一个用于您的 Web 应用程序,那么您的 Web 应用程序可以看到 log4j(因为 JAR 是 WEB-INF/lib),但 Jetty 的类加载器看不到。
如果您设法使 Jetty 可以使用一个类(例如数据库层中的某些内容),该类使用 log4j 但最终在 Jetty 的上下文(和类加载器)中运行,您将收到错误。
要调试此问题,请在 org.springframework.web.util.Log4jWebConfigurer.initLogging() 中设置断点。如果可以的话,将此类的源代码复制到您的项目中(之后不要忘记将其删除)并添加以下行:
ClassLoader cl = Thread.currentThread().getContextClassLoader();
查看调试器中的 cl 对象。这应该会给你一些创建它的人的信息。我的猜测是这是来自 Jetty 的类加载器。
[编辑]请注意,如果两个类加载器中都有 log4j,您会陷入不同的困惑:在这种情况下,您将拥有两个 具有相同名称的类,其中创建与赋值不兼容的对象!因此,请确保该 jar 只有一个实例,或者 log4j 的实例永远不会在两个上下文之间传递(这通常是不可能的)。
关于java - 为什么 Java 类加载在 Linux 上失败,但在 Windows 上成功?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/519816/
我是一名优秀的程序员,十分优秀!