`

一次jboss中部署应用时类版本冲突问题分析、解决过程

    博客分类:
  • java
阅读更多
去年同事的一个项目在JBOSS中部署时遇到类版本冲突问题,当时协助他处理了此问题,现在将当时处理的过程记录一下,以备以后参考使用。错误日志如下:
2010-12-13 17:06:00,101 ERROR [STDERR] Exception in thread "DefaultQuartzScheduler_Worker-1" 
2010-12-13 17:06:00,101 ERROR [STDERR] java.lang.NoSuchMethodError: org.codehaus.jettison.AbstractXMLStreamWriter.getSerializedAsArrays()Ljava/util/ArrayList;
2010-12-13 17:06:00,101 ERROR [STDERR]  at com.thoughtworks.xstream.io.json.JettisonStaxWriter.startNode(JettisonStaxWriter.java:71)
2010-12-13 17:06:00,101 ERROR [STDERR]  at com.thoughtworks.xstream.io.WriterWrapper.startNode(WriterWrapper.java:33)
2010-12-13 17:06:00,101 ERROR [STDERR]  at com.thoughtworks.xstream.io.path.PathTrackingWriter.startNode(PathTrackingWriter.java:44)
2010-12-13 17:06:00,101 ERROR [STDERR]  at com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper.startNode(ExtendedHierarchicalStreamWriterHelper.java:17)
2010-12-13 17:06:00,101 ERROR [STDERR]  at com.thoughtworks.xstream.core.TreeMarshaller.start(TreeMarshaller.java:96)
2010-12-13 17:06:00,101 ERROR [STDERR]  at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.marshal(AbstractTreeMarshallingStrategy.java:38)
2010-12-13 17:06:00,101 ERROR [STDERR]  at com.thoughtworks.xstream.XStream.marshal(XStream.java:837)
2010-12-13 17:06:00,102 ERROR [STDERR]  at com.thoughtworks.xstream.XStream.marshal(XStream.java:826)
2010-12-13 17:06:00,102 ERROR [STDERR]  at com.thoughtworks.xstream.XStream.toXML(XStream.java:801)
2010-12-13 17:06:00,102 ERROR [STDERR]  at com.thoughtworks.xstream.XStream.toXML(XStream.java:789)
2010-12-13 17:06:00,102 ERROR [STDERR]  at org.springframework.batch.core.repository.dao.XStreamExecutionContextStringSerializer.serialize(XStreamExecutionContextStringSerializer.java:43)

    从上面的日志可以看出spring batch 依赖的jettison的AbstractXMLStreamWriter类找不到getSerializedAsArrays(java.util.ArrayList)方法。遇到这个问题,我们很自然的先检查一下xxxx-ear.ear/lib/codehaus.jettison-1.0.1.jar这个jar中的AbstractXMLStreamWriter类是否符合要求,检查结果这个类存在getSerializedAsArrays(java.util.ArrayList)方法。这样也就是说jboss没有加载到ear包中的类。
    下面我们来跟踪一下,看看应用究竟在那个jar里加载了AbstractXMLStreamWriter类。首先我们需要修改一下jboss log4j的配置,这个配置的意思相信大家一看就了解了。
<appender name="UCL" class="org.apache.log4j.FileAppender">
        <param name="File" value="/home/sean/output/logs/user/ucl.log"/>
        <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="[%r,%c{1},%t] %m%n"/>
        </layout>
    </appender>

    <category name="org.jboss.mx.loading" additivity="false">
        <priority value="TRACE" class="org.jboss.logging.XLevel"></priority>
        <appender-ref ref="UCL"></appender-ref>
    </category>
 
       
然后,我们查看ucl的日志可以看到下列信息
[10141,ClassLoaderUtils,main] Indexed pkg: org.codehaus.jettison, UCL: org.jboss.mx.loading.UnifiedClassLoader3@1fe500a{ url=file:/home/sean/web-deploy/jboss_server/default/deplo
y/jbossws.sar/ ,addedOrder=12}
[10141,ClassLoaderUtils,main] Indexed pkg: org.codehaus.jettison.badgerfish, UCL: org.jboss.mx.loading.UnifiedClassLoader3@1fe500a{ url=file:/home/sean/web-deploy/jboss_server/de
fault/deploy/jbossws.sar/ ,addedOrder=12}
[10142,ClassLoaderUtils,main] Indexed pkg: org.codehaus.jettison.json, UCL: org.jboss.mx.loading.UnifiedClassLoader3@1fe500a{ url=file:/home/sean/web-deploy/jboss_server/default/
deploy/jbossws.sar/ ,addedOrder=12}
[10143,ClassLoaderUtils,main] Indexed pkg: org.codehaus.jettison.mapped, UCL: org.jboss.mx.loading.UnifiedClassLoader3@1fe500a{ url=file:/home/sean/web-deploy/jboss_server/defaul
t/deploy/jbossws.sar/ ,addedOrder=12}
[10144,ClassLoaderUtils,main] Indexed pkg: org.codehaus.jettison.util, UCL: org.jboss.mx.loading.UnifiedClassLoader3@1fe500a{ url=file:/home/sean/web-deploy/jboss_server/default/
deploy/jbossws.sar/ ,addedOrder=12}
[10144,RepositoryClassLoader,main] Added url: file:/home/sean/output/logs/jboss_stout/tmp/deploy/tmp8907418620370263381jettison.jar, to ucl: org.jboss.mx.loading.UnifiedClassLoad
er3@1fe500a{ url=file:/home/sean/web-deploy/jboss_server/default/deploy/jbossws.sar/ ,addedOrder=12}

从上面的日志可以看出有个jettison.jar加到了这个ucl org.jboss.mx.loading.UnifiedClassLoader3@1fe500a中。从日志里还可以看到这个jar存在的路径是/home/sean/web-deploy/jboss_server/default/deploy/jbossws.sar/

再来看一段日志
[19814,ClassLoaderUtils,main] Multiple class loaders found for pkg: org.codehaus.jettison.badgerfish
[19814,ClassLoaderUtils,main] Indexed pkg: org.codehaus.jettison.badgerfish, UCL: org.jboss.mx.loading.UnifiedClassLoader3@16274ea{ url=file:/home/sean/output/logs/jboss_stout/tm
p/deploy/tmp7754042895360577419xxxx-ear.ear ,addedOrder=45}
[19814,ClassLoaderUtils,main] Multiple class loaders found for pkg: org.codehaus.jettison
[19814,ClassLoaderUtils,main] Indexed pkg: org.codehaus.jettison, UCL: org.jboss.mx.loading.UnifiedClassLoader3@16274ea{ url=file:/home/sean/output/logs/jboss_stout/tmp/deploy/tm
p7754042895360577419xxxx-ear.ear ,addedOrder=45}
[19814,ClassLoaderUtils,main] Multiple class loaders found for pkg: org.codehaus.jettison.json
[19814,ClassLoaderUtils,main] Indexed pkg: org.codehaus.jettison.json, UCL: org.jboss.mx.loading.UnifiedClassLoader3@16274ea{ url=file:/home/sean/output/logs/jboss_stout/tmp/depl
oy/tmp7754042895360577419xxxx-ear.ear ,addedOrder=45}
[19815,ClassLoaderUtils,main] Multiple class loaders found for pkg: org.codehaus.jettison.util
[19815,ClassLoaderUtils,main] Indexed pkg: org.codehaus.jettison.util, UCL: org.jboss.mx.loading.UnifiedClassLoader3@16274ea{ url=file:/home/sean/output/logs/jboss_stout/tmp/depl
oy/tmp7754042895360577419xxxx-ear.ear ,addedOrder=45}
[19815,ClassLoaderUtils,main] Multiple class loaders found for pkg: org.codehaus.jettison.mapped
[19815,ClassLoaderUtils,main] Indexed pkg: org.codehaus.jettison.mapped, UCL: org.jboss.mx.loading.UnifiedClassLoader3@16274ea{ url=file:/home/sean/output/logs/jboss_stout/tmp/de
ploy/tmp7754042895360577419xxxx-ear.ear ,addedOrder=45}
[19816,RepositoryClassLoader,main] Added url: file:/home/sean/output/logs/jboss_stout/tmp/deploy/tmp7754042895360577419xxxx-ear.ear-contents/lib/codehaus.jettison-1.0.1.jar, t
o ucl: org.jboss.mx.loading.UnifiedClassLoader3@16274ea{ url=file:/home/sean/output/logs/jboss_stout/tmp/deploy/tmp7754042895360577419xxxx-ear.ear ,addedOrder=45}

从上面的日志可以看到又有一个codehaus.jettison-1.0.1.jar加到了这个ucl org.jboss.mx.loading.UnifiedClassLoader3@16274ea中这个是我们应用自己的jar(xxxx-ear.ear-contents/lib/codehaus.jettison-1.0.1.jar,)
        
在应用加载AbstractXMLStreamWriter类时出现了如下日志
[70806,RepositoryClassLoader,DefaultQuartzScheduler_Worker-9] loadClass org.jboss.mx.loading.UnifiedClassLoader3@1fe500a{ url=file:/home/sean/web-deploy/jboss_server/default/depl
oy/jbossws.sar/ ,addedOrder=12} name=org.codehaus.jettison.AbstractXMLStreamWriter class=class org.codehaus.jettison.AbstractXMLStreamWriter cl=org.jboss.mx.loading.UnifiedClassLo
ader3@1fe500a{ url=file:/home/sean/web-deploy/jboss_server/default/deploy/jbossws.sar/ ,addedOrder=12}

    从这个日志中我们可以看出来AbstractXMLStreamWriter是从org.jboss.mx.loading.UnifiedClassLoader3@1fe500a中加载到的也就是说这个class来自/home/sean/web-deploy/jboss_server/default/deploy/jbossws.sar/下的jettison.jar中,根本就不是应用想要的类。

    为什么会出现上面这样的情况呢???
    这就要从jboss的类加载机制说起。请查看我以前写的一篇关于jboss classloader的分析文章

分析了问题的原因之后,我们来看一下如何解决此问题
参考这里http://community.jboss.org/wiki/JBossClassLoadingUseCases的介绍,我一开始是参考Case 3的做法将ear的Repository和应用服务器中的默认的Repository进行隔离。实现如下结构

引用

Because Java2ParentDelegation is turned off by default, the Step (1.1) is never executed,parentRepository.getCachedClass() never gets called, so the UCL doesn't have access to the repository'scached classes.

Within the scope of the call to getPackageClassLoaders() at Step 3, the child repository also callsgetPackageClassLoaders() on its parent, and also includes into the returned class loader set a UCL (constructed on the spot and associated to the child repository) that has among its ancestors an instance ofNoAnnotationURLClassLoader, which ultimately can reach the system class loader. Why is that? Remember that the UCL's parent, HierarchicalLoaderRepository3$NoParentClassLoader, overrides loadClass() to always throw a ClassNotFoundException, thus forcing the UCL to only load from its URLs. If the UCL relies only on its class loader parent to load bootstrap classes, it will throw ClassNotFoundException and fail when your application wants to load "java.lang.String", for example. The NoAnnotationURLClassLoader-delegating UCL instance included in the return set provides a way load bootstrap library classes.

Always the HierarchialLoaderRepository's class loaders take precedence over the parent's (their "order" is lower). For the case depicted above, UCL1 is the preferred class loader.

按原文描述的意思大致就是在应用的UCL加载类的时候不会去调用父Repository的getCachedClass()方法,在执行loadClassImpl()方法是会调用父getCachedClass()的getPackageClassLoaders()方法。但是即便返回的ucl集合包含父Repository的ucl HierarchialLoaderRepository3也会保证自己包含的UCL的优先级高于父类的UCL。
具体如何修改配置实现如上所说的隔离效果请看http://community.jboss.org/wiki/ClassLoadingConfiguration的说明

但是在我实际操作的过程中并没有上面的文档说的这么简单。在做了如上的操作以后应用启动失败,有个ejb部署失败(准确来说是一个MDB)报错如下:
2010-12-11 23:39:23,513 ERROR [org.jboss.deployment.MainDeployer] Could not create deployment: file:/home/sean/output/logs/jboss_stout/tmp/deploy/tmp869229660270410713xxxx-ear.ear-contents/lib/xxxx.components.financestat-1.0.jar
org.jboss.deployment.DeploymentException: Verification of Enterprise Beans failed, see above for error messages.
        at org.jboss.ejb.EJBDeployer.create(EJBDeployer.java:610)
        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.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
        at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
        at org.jboss.mx.interceptor.AbstractInterceptor.invoke(AbstractInterceptor.java:133)

对于这一块报错的原因,由于日志提示的不是很明确,当时时间也比较紧就没有再研究下。如果各位了解此问题的话望不吝赐教。

下面我介绍一下我最后使用的解决办法:
因为前面也介绍了导致问题的原因是由于:

org.jboss.mx.loading.UnifiedClassLoader3@1fe500a{ url=file:/home/sean/web-deploy/jboss_server/default/deploy/jbossws.sar/ ,addedOrder=12}的优先级高于ucl: org.jboss.mx.loading.UnifiedClassLoader3@16274ea{ url=file:/home/sean/output/logs/jboss_stout/tmp/deploy/tmp7754042895360577419xxxx-ear.ear ,addedOrder=45}的优先级。
那么如果将jbossws.sar的Repository和jboss的Repository进行隔离的话这样在jboss的Repository里就不存在jettison.jar了。因为我们的应用使用不到jboss webservice功能,所以这个改动不会影响到我们的程序。
具体配置方法是在$JBOSS_SERVER_HOME/deploy/jbossws.sar/META-INF/jboss-service.xml里添加如下配置项
<loader-repository>
          com.example:archive=nouse
   </loader-repository>

现在再来看一下日志,已经是我们想要的效果了。
[116920,RepositoryClassLoader,DefaultQuartzScheduler_Worker-8] loadClass org.jboss.mx.loading.UnifiedClassLoader3@abe02e{ url=file:/home/sean/output/logs/jboss_stout/tmp/deploy/t
mp429376920320337088xxxx-ear.ear ,addedOrder=45} name=org.codehaus.jettison.AbstractXMLStreamWriter class=class org.codehaus.jettison.AbstractXMLStreamWriter cl=org.jboss.mx.lo
ading.UnifiedClassLoader3@abe02e{ url=file:/home/sean/output/logs/jboss_stout/tmp/deploy/tmp429376920320337088xxxx-ear.ear ,addedOrder=45}

以上内容是我通过查看jboss文档和jboss、tomcat相关代码后对jboss、tomcat的类加载机制的不完全分析。其中可能有些理解错误的地方,欢迎大家斧正。
2
5
分享到:
评论

相关推荐

    jboss热部署配置

    4. **使用专用的部署目录**:为了避免与默认的`deploy`目录冲突,创建一个新的目录(如`deployments_in_progress`),并将其添加到`jboss-service.xml`的`deployment-scanner`元素中。这样,当在该目录下添加或更新...

    JBoss部署Web Project时的问题——请刷新

    最后,对于【压缩包子文件的文件名称列表】中的"JBoss部署Web Project时的问题——更改不能显示结果请刷新",这可能是具体的日志或错误信息,通过分析这些内容可以进一步定位问题所在。记住,详细的错误日志是解决...

    jdk1.6与jboss5.x冲突问题的解决方法

    标题中的“jdk1.6与jboss5.x冲突问题的解决方法”指的是在使用Java Development Kit(JDK)1.6版本与JBoss Application Server 5.x版本进行集成时可能出现的兼容性问题。JBoss AS是一款开源的企业级Java应用程序...

    jboss7.1 linux版本

    在这个环境中,JBoss AS 7.1不支持Java Development Kit (JDK) 1.8,因此在安装和配置时需确保使用的是兼容的JDK版本,如JDK 1.6或1.7。 首先,让我们详细了解一下JBoss AS 7.1.0.Final的关键特性: 1. **模块化**...

    windows下JBOSS5.1.0部署web应用

    在Windows环境下部署JBOSS 5.1.0作为Web应用服务器,涉及到一系列配置步骤,包括集成Spring框架、设置环境变量、修改默认配置以及配置SSL安全连接。以下是对这些步骤的详细说明: 1. **下载JBOSS-5.1.0.GA-jdk6.zip...

    JBoss 将WEB应用发布为默认应用程序

    `WEB-INF`是一个特殊目录,包含了Web应用的配置文件、类文件以及库文件等,JBoss服务器在部署应用时会读取这些文件。 3. **部署应用**:将整个WEB应用(包括`WEB-INF`目录和`jboss-web.xml`)打包成WAR文件,然后将...

    一台机器部署多个jboss说明

    然而,在同一台机器上部署多个JBoss实例时,必须注意端口冲突的问题。本文将详细介绍如何在一台机器上成功部署多个JBoss服务器,并重点讲解如何正确地配置这些服务器以避免端口冲突。 #### 一、理解端口冲突问题 ...

    jboss部署jar包的bat脚本

    对于开发者来说,快速部署应用程序是日常工作中必不可少的一部分。本篇将详细介绍如何通过bat(批处理)脚本来自动化部署jar包到JBoss服务器。 首先,让我们了解bat脚本的基本概念。在Windows操作系统中,bat脚本是...

    jboss配置及项目部署文档

    JBoss 是一个开源的应用服务器,基于Java EE标准,用于托管企业级Java应用程序。在这个配置及项目部署文档中,我们将深入探讨如何...在实际操作中,还可能遇到各种问题,如权限问题、依赖冲突等,需要逐一排查解决。

    JBoss JMX实现架构

    在JBoss这样的应用服务器中,理解这些异常及其原因至关重要,因为它们可以帮助诊断和解决动态部署过程中可能出现的问题。通过优化类加载器的策略和管理,可以提高系统的稳定性和可扩展性。 总之,JBoss JMX的实现...

    在eclipse中配置 jboss 图解

    在本文中,我们将详细介绍如何在Eclipse集成开发环境中配置JBoss应用服务器,这是一个关键步骤,对于Java开发者来说尤其重要,因为JBoss是流行的开源应用服务器,常用于部署和管理Java应用程序。首先,确保你的Java...

    关于JBoss5加载项目的完整过程以及相关错误解决

    JBoss5.1.0.GA是一个成熟的Java应用服务器,用于部署和管理Web应用程序。在这个过程中,最常见的部署格式是WAR(Web Application Archive),它是一个包含所有必要资源和配置的压缩文件。以下是JBoss5加载WAR项目的...

    jboss4.0.5-GA在使用RMI时的大坑

    压缩包中的"jboss+classloader分享.ppt"很可能包含了一个关于JBOSS类加载机制的详细讲解,这将有助于理解类加载如何影响RMI的使用,以及如何解决相关的类冲突问题。这个PPT可能涵盖了以下内容: - JBOSS类加载层次...

    用JBOSS CACHE 做CAS集群在weblogic上部署的问题

    标题中的“用JBOSS CACHE做CAS集群在weblogic上部署的问题”涉及到的是一个特定的分布式缓存解决方案在不同应用服务器环境下的集成问题。CAS(Central Authentication Service)是一种开源的身份验证服务,它允许...

    jboss打包不起作用,替换jar即可

    当我们遇到"jbos打包不起作用,替换jar即可"的问题时,通常意味着在进行JBoss应用部署过程中遇到了某些库文件的不兼容或缺失问题。下面我们将详细讨论这个问题及其解决方案。 首先,我们需要理解JBoss的工作原理。...

    Apache安装及jboss部署说明文档

    在实际操作过程中,可能会遇到各种错误,比如端口冲突、配置语法错误、类加载问题等。解决这些问题通常需要查阅官方文档,检查配置文件,或者通过日志定位错误原因。文档中提到,作者的经验主要基于CentOS 4.4、...

    最详细的JBOSS使用手册

    JBOSS模块系统负责管理类加载和依赖关系,每个模块都有自己的命名空间和依赖关系,避免了类冲突问题。 七、安全管理 JBOSS支持角色基础的访问控制(RBAC)和认证机制,可以设置不同用户和角色的权限,保障系统安全...

Global site tag (gtag.js) - Google Analytics