多Jetty容器中的Java类装入器问题/Maven问题

多Jetty容器中的Java类装入器问题/Maven问题,java,spring,maven,jetty,containers,Java,Spring,Maven,Jetty,Containers,我有一个使用多个应用程序运行的大型设备。我有多个Jetty容器,其中每个容器部署了多个应用程序。。现在,在部署应用程序时,我面临一个简单的类未找到警告 这是我的分析: JettyContainer_1包含App_1,App_1有许多通用JAR文件,可以在所有其他容器中共享,因此所有应用程序都可以访问这些JAR文件 现在,问题是JettyContainer_1中共享libs中的一个spring框架类正试图从容器3中的App_X加载一个类“ClassAInContainer3”(来自jar文件)。然

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

这是我的分析:

  • JettyContainer_1包含App_1,App_1有许多通用JAR文件,可以在所有其他容器中共享,因此所有应用程序都可以访问这些JAR文件
  • 现在,问题是JettyContainer_1中共享libs中的一个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构建应用程序。。我怀疑这是因为两个LIB位于不同的位置,spring类(存在于jettyContainer1中)无法从App_3加载ClassAInContainer3。因此,我们可以添加一些依赖项或类加载器配置


    如有任何意见,我们将不胜感激。。提前感谢……)

    如果“spring framework类”由Jetty类加载器加载,而
    ClassAInContainer3
    WebAppClassLoader
    加载(如果它位于webapp的WEB-INF/lib或WEB-INF/classes中,则通常是这样),则异常是有意义的

    我在debug中启动了一个Jetty服务器,并在web控制器内的一个breack点被阻塞时执行了以下命令(在Eclipse的显示视图中)(即,我正在执行由
    WebAppClassLoader
    加载的代码):

    如果我尝试爬升类加载器层次结构,我会得到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容器将使用“parentlast”加载策略,但请注意,正如我前面所述,除了
    AppClassLoader
    )之外,没有其他类加载器

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

    this.getClass().getClassLoader()
        org.eclipse.jetty.webapp.WebAppClassLoader) WebAppClassLoader=653648989@26f5e45d
    
    this.getClass().getClassLoader().getParent().loadClass("org.test.showcase.HomeController")
        Evaluation failed. Reason(s):
            An exception occurred: java.lang.ClassNotFoundException
    

    这正是我所怀疑的情况。

    如果“spring framework类”由Jetty类装入器装入,而
    ClassAInContainer3
    WebAppClassLoader
    装入(如果它在webapp的WEB-INF/lib或WEB-INF/classes中,通常是这样),则异常是有意义的

    我在debug中启动了一个Jetty服务器,并在web控制器内的一个breack点被阻塞时执行了以下命令(在Eclipse的显示视图中)(即,我正在执行由
    WebAppClassLoader
    加载的代码):

    如果我尝试爬升类加载器层次结构,我会得到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容器将使用ParentLast“加载策略,但请注意,正如我前面所述,除了
    AppClassLoader
    )之外,没有其他类加载器

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

    this.getClass().getClassLoader()
        org.eclipse.jetty.webapp.WebAppClassLoader) WebAppClassLoader=653648989@26f5e45d
    
    this.getClass().getClassLoader().getParent().loadClass("org.test.showcase.HomeController")
        Evaluation failed. Reason(s):
            An exception occurred: java.lang.ClassNotFoundException
    

    这正是我所怀疑的情况。

    共享库似乎不是问题。共享库似乎不是问题。因此,是否有任何方法可以将一个类从一个web容器加载到另一个web容器……问题不在于您有两个容器,也不在于共享库的位置(至少这是我的理解)。关键是类的加载顺序。如果您能够传递正确的类加载器,那么您可以使用它来加载您感兴趣的类。我想,这在您的系统中是否可行,这需要您理解。@abyin007您发现了什么吗?那么,有什么方法可以让我从一个类加载类呢web容器到另一个web容器…问题不在于您有2个容器,也不在于共享库的位置(至少这是我的理解)。关键是类的加载顺序。如果您能够传递正确的类加载器,那么您可以使用它来加载您感兴趣的类。我想,这在您的系统中是否可行,这需要您理解。@abyin007您发现了什么吗?