多个Jetty容器中的Java类加载器问题/ Maven问题

时间:2015-08-19 07:50:17

标签: java spring maven jetty containers

我有一个使用多个应用程序运行的大型设备。我有多个Jetty容器,每个容器都部署了多个应用程序。现在,我在部署应用程序时面临一个简单的类未找到警告。

这是我的分析:

  1. JettyContainer_1包含App_1,它有许多常见的JAR文件,可以在所有其他容器中共享,因此所有应用程序都可以访问这些JAR文件。
  2. 现在,问题是JettyContainer_1中的共享库中的spring框架类正在尝试从容器3中的App_X加载类" ClassAInContainer3"(来自jar文件)。然后我找不到类错误..
  3. 这是堆栈跟踪..

    Caused by: java.lang.ClassNotFoundException: com.test.ClassAInContainer3
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366) ~[na:1.7.0_55]
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355) ~[na:1.7.0_55]
        at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_55]
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354) ~[na:1.7.0_55]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425) ~[na:1.7.0_55]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358) ~[na:1.7.0_55]
        at org.springframework.util.ClassUtils.forName(ClassUtils.java:258) ~[spring-core.jar:3.2.0.RELEASE]
        at org.springframework.amqp.support.converter.DefaultJavaTypeMapper.getClassIdType(DefaultJavaTypeMapper.java:82) ~[spring-amqp.jar:na]
        ... 16 common frames omitted
    2015-08-19 05:38:16.123 UTC,WARN ,App1-web,messaging,com.test.Rabbit,null,SimpleAsyncTaskExecutor-1,Caught an exception while handling a rabbitmq message, Publisher/Consumer should have handled this.
    org.springframework.amqp.support.converter.MessageConversionException: failed to resolve class name. Class not found [com.test.ClassAInContainer3]
        at org.springframework.amqp.support.converter.DefaultJavaTypeMapper.getClassIdType(DefaultJavaTypeMapper.java:85) ~[spring-amqp.jar:na]
        at org.springframework.amqp.support.converter.DefaultJavaTypeMapper.toJavaType(DefaultJavaTypeMapper.java:53) ~[spring-amqp.jar:na]
        at org.springframework.amqp.support.converter.JsonMessageConverter.fromMessage(JsonMessageConverter.java:117) ~[spring-amqp.jar:na]
    

    关于如何解决此问题的任何输入..我正在使用Maven来构建应用程序..我怀疑这是becoz,因为两个库都位于不同的位置,spring类(存在于jettyContainer1中)无法从App_3加载ClassAInContainer3。所以我们可以添加一些依赖项或类加载器配置..

    任何输入都将非常感谢..提前感谢.. :))

1 个答案:

答案 0 :(得分:0)

如果" spring框架类"那么例外是有意义的。由Jetty类加载器加载,ClassAInContainer3加载WebAppClassLoader(通常是这样,如果它在WEB-INF / lib或WEB-INF / webapp类中)。

我在调试中启动了一个Jetty服务器并执行了以下命令(在Eclipse的Display视图中),同时在Web控制器内的一个breack点被阻塞(即我执行WebAppClassLoader加载的代码):

this.getClass().getClassLoader()
    org.eclipse.jetty.webapp.WebAppClassLoader) WebAppClassLoader=653648989@26f5e45d

如果我尝试爬上类加载器层次结构,我会得到Jetty的服务器类加载器:

this.getClass().getClassLoader().getParent()
    (org.codehaus.plexus.classworlds.realm.ClassRealm) ClassRealm[plugin>org.eclipse.jetty:jetty-maven-plugin:9.3.2.v20150730, parent: sun.misc.Launcher$AppClassLoader@58644d46]

这是根类加载器,超出这一点我不能去,事实上:

this.getClass().getClassLoader().getParent().getParent()
    null

现在,如果我在loadClass加载的类的代码中调用AppClassLoader(通常在服务器启动时),它将首先使用自己的类加载器(也就是说,AppClassLoader本身)然后,如果找不到类,那么父类加载器(因为servlet容器将使用"父最后一个"加载策略,但请注意,我之前说过,除AppClassLoader之外没有其他类加载器。

但AppClassLoader无法访问ClassAInContainer3是完全可行的,因为它不在其已知的类路径中。事实上,如果我尝试使用AppClassLoader加载我的Web控制器实例(WEB-INF / classes中包含的类)会发生什么:

this.getClass().getClassLoader().getParent().loadClass("org.test.showcase.HomeController")
    Evaluation failed. Reason(s):
        An exception occurred: java.lang.ClassNotFoundException

我怀疑你的情况正是如此。