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

标签 java spring maven jetty containers

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

这是我的分析:

  1. JettyContainer_1 包含 App_1,该 App_1 具有许多通用 JAR 文件,这些文件可以在所有其他容器之间共享,以便所有应用程序都可以访问这些 JAR 文件。
  2. 现在的问题是,JettyContainer_1 中的共享库中的 Spring 框架类正在尝试从容器 3 中的 App_X 加载类“ClassAInContainer3”(来自 jar 文件)。然后出现找不到类错误。

这是堆栈跟踪..

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 来构建应用程序..我怀疑这是因为两个库位于不同的位置,spring 类(存在于 jettyContainer1 中)无法从 App_3 加载 ClassAInContainer3。所以也许我们可以添加一些依赖项或类加载器配置..

任何意见将不胜感激..提前致谢..:)

最佳答案

如果“spring 框架类”由 Jetty 类加载器加载,并且 ClassAInContainer3WebAppClassLoader 加载(通常是这样,如果它位于 Web 应用程序的 WEB-INF/lib 或 WEB-INF/classes 中)。

我在调试中启动了 Jetty 服务器,并执行了以下命令(在 Eclipse 的“显示” View 中),同时在 Web Controller 内的断点处受阻(即,我正在执行由 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

现在,如果我在由 AppClassLoader 加载的类的代码中调用 loadClass(通常在服务器启动时),它将首先使用自己的类加载器(即 AppClassLoader 本身),然后,如果未找到该类,则使用父类加载器(因为 servlet 容器将使用“父级最后”加载策略,但请注意,正如我之前所说,除此之外没有其他类加载器) AppClassLoader)。

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

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

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

关于多个 Jetty 容器中的 Java 类加载器问题/Maven 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32089547/

相关文章:

java - spring mvc 框架上的流式 api 问题

java - 对第三方库使用 Maven 的阴影插件?

maven - 无法使用 Jar 将 Pom 部署到 Artifactory

java - 如何使用 mstor 阅读 mbox 电子邮件

java - 在 Java 中对资源使用 try 是否安全 - 它是否检查 closeable 是否不为 null 并在尝试关闭它时是否捕获异常

java - 带有 Spring RESTTemplate 的泛型

java - 在 WildFly 上部署 Spring Boot WAR

java - Maven:如何重命名项目的war文件?

Java 如何在 IST 中打印时间

java - 如何跟踪 Java 中的方法调用?