【问题标题】:How to load a java class from one web container to another?如何将 Java 类从一个 Web 容器加载到另一个 Web 容器?
【发布时间】:2015-08-20 07:26:23
【问题描述】:

我有一个在码头容器中运行的应用程序,其中一个自定义类加载器将从 /SHARED/ 加载类。现在我希望这些加载的类中的任何一个使用另一个类 (WEB-INF/libs)来自运行时在另一个码头容器中运行的应用程序。截至目前,我遇到了一个找不到类的异常。

网络容器 1:

Jar 位置:/ci/Shared/ 为了加载上述 jar,我们有一个名为 SharedJarsClassLoader 的客户类加载器。

网络容器 2:

App_1/WEB-INF/libs App_2/WEB-INF/libs

我的要求是支持容器 1 中 /ci/Shared/ 中的类从 WEB-INF/libs 中加载 app1 和 app2 jar 中的类。

到目前为止,当应用程序启动时,它的显示类未找到异常。应用无法从 App_1/WEB-INF/libs & App_2/WEB-INF/libs 加载类。

这是类加载器层次结构..

sun.misc.Launcher$ExtClassLoader@4921a90                                         (Extensions class loader)
  sun.misc.Launcher$AppClassLoader@3da997a                                       (System class loader)
    startJarLoader@68758d51                                                      (Jetty class loader)
      com.test.jetty_ext.NewWebAppProvider$SharedJarsClassLoader@374d1cbd        (Shared jars class loader)
        WebAppClassLoader=settings@2fee2019                                      (Webapp class loader)
        WebAppClassLoader=taskt@6a57cf0b                                         (2nd Webapp class loader)

这是堆栈跟踪..

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]

关于如何解决此问题的任何意见?

【问题讨论】:

    标签: java maven jetty containers classloader


    【解决方案1】:

    为此,您的自定义类加载器 (CCL) 必须是 Web 应用类加载器的子级。原因是类加载器只向它的父级询问缺少的类。在你的情况下,情况正好相反。这意味着:

    • 应用程序代码通过 CCL 访问自定义类。这是可行的,因为 CCL 是您应用的类加载器的父级。
    • 自定义类现在尝试发现另一个应用程序类。它询问不知道is的CCL。然后CCL问父母谁也不知道->厄运。

    如果您将其颠倒过来,自定义类将能够访问应用代码。现在您将无法访问自定义类。为了解决这个问题,您必须传递 CCL 引用并使用 CCL 通过类加载器 API 手动加载类型,并实例化您需要的类型。您不能让 Java“自动”发现这些类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-13
      • 1970-01-01
      • 2020-07-21
      相关资源
      最近更新 更多