gpt4 book ai didi

java - 为什么 Java 类加载在 Linux 上失败,但在 Windows 上成功?

转载 作者:行者123 更新时间:2023-11-30 06:39:43 26 4
gpt4 key购买 nike

我有一个 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com