Java Jboss 5、类加载器和多个类实例

Java Jboss 5、类加载器和多个类实例,java,jboss,dependencies,Java,Jboss,Dependencies,我的申请有问题。为了恢复这个问题,我不得不将一个应用程序从JBoss4迁移到JBoss5 在战争部署期间,我犯了以下错误: java.lang.LinkageError: loader constraint violation: when resolving field "DATETIME" the class loader (instance of org/jboss/classloader/spi/base/BaseClassLoader) of the referring class, j

我的申请有问题。为了恢复这个问题,我不得不将一个应用程序从JBoss4迁移到JBoss5

在战争部署期间,我犯了以下错误:

java.lang.LinkageError: loader constraint violation: when resolving field "DATETIME"
the class loader (instance of org/jboss/classloader/spi/base/BaseClassLoader) of the referring class,
javax/xml/datatype/DatatypeConstants, and the class loader (instance of <bootloader>)
for the field's resolved type, javax/xml/namespace/QName,
have different Class objects for that type
java.lang.LinkageError:加载程序约束冲突:解析字段“DATETIME”时
引用类的类加载器(org/jboss/classloader/spi/base/BaseClassLoader的实例),
javax/xml/datatype/DatatypeConstants和类加载器(的实例)
对于字段的解析类型javax/xml/namespace/QName,
该类型具有不同的类对象
经过多次搜索,我发现这个错误在这里,因为我有好几次在不同的包中使用同一个类。一次在依赖项包中(从我的pom.xml),一次由jboss提供

因此,为了解决这个问题,我为我的依赖项提供了一个作用域

但我不明白为什么这个解决方案有效。我认为在一个应用程序中有几次相同的类是有效的。我知道这不是一件好事,但对于JBoss4来说,这是一件好事

有人可以向我解释为什么它与JBoss4而不是JBoss5一起工作


感谢您的解释:)

您看到的是应用服务器在单独的类加载器中加载JBoss库和EAR库的效果

您可以认为EAR的类加载器层次结构类似(但不一定)于:

引导类装入器->系统类装入器->JBoss系统类装入器->Ear类装入器->War类装入器

其中war类装入器的父级是ear类装入器,依此类推

现在,如果引导类Loader加载了一个jar a,并且ear也与jar a一起部署,那么引导类Lodaer和ear类Loader将在单独的类装入器中创建两次相同的类

我假设(不是100%确定)JBoss4没有与javax/xml/namespace/QName捆绑在一起。如果这是真的,JBoss5很可能是一个不同的升级版Java(4->5或5->6)。因此(在新的JBoss5中),当您尝试将javax/xml/namespace/QName传递到一个类中时,它期望从ear获得该类。但是,由于类加载器的首选项(父类优先,等等),您从引导类加载器中为它提供QName类

由于类类型相等,但类实例不相等,因此会出现LinkageError

编辑:

只有两个解决这两个问题-

jtahlborn指出的类加载行为是完全不同的。在正常应用程序中,像QName这样的系统类将在引导类加载器中一致地查找。在错误中,javax/xml/datatype/DatatypeConstants似乎正在org/jboss/classloader/spi/base/BaseClassLoader中加载。让我们假设这是EAR类装入器(或WAR)。快速的google展示了它是XMLAPI家族的一部分,可能还有jaxp api

因此,在代码中的某个地方(或位于EAR类加载器中的另一个库代码)需要DatatypeConstants—这强制在EAR类加载器中查找类。QName对象的创建虽然从引导类加载器(而不是EAR)加载了类。如果系统已经初始化了QName类(可能已经初始化了),就会发生这种情况

正如你所想象的那样,这是不应该发生的。事实上,看起来你的父母是最后一个。因为当从JBoss类加载机制加载类时,如果首先启用父类,则初始DatatypeConstants将返回父类(引导)DatatypeConstants,而不是子类。因此,正如jtahlborn所指出的,您希望忽略这里的儿童类加载器


就解决方案而言,除非您出于特定的原因需要依赖项(比如稍微更新的版本比当前版本更好),否则我将委托jboss实现。如果不是这样,您可以查看jboss配置中的
类加载java2ClassLoadingCompliance
元素。

-verbose:class
在VM参数中会给出类的加载方式。
如果存在重复项,您可以删除冲突的jar。

感谢您的解释-这非常有帮助

我了解到这个问题与JBoss的一个bug有关,这个bug在5.0.0版本中得到了修复。但是,即使我运行的是JBoss的旧版本,我仍然会遇到这个错误。 无论如何,我做了广泛的研究并运行了几次maven依赖树,以查看重复定义的来源。我终于能够通过向我的主pom添加两个依赖项(范围设置为provided)来解决此错误:

(sun.jaxb-impl 2.1,javax.jaxb-api 2.2)我希望这些信息能帮助一些人。

我认为这很接近,但并不完全正确。通常,war类装入器设置为更喜欢从子类装入。否则,您将永远不会看到冲突,因为战争中的类版本将被忽略。您是对的,最有可能的问题是java版本的差异(我怀疑jboss是否包括jaxb类)。通过将websphere和weblogic升级到新版本(包括java的新版本),我了解到java运行时包含了自己的javax/xml/namespace/QName和相关库。这就是我认为OP的问题所在。是的,您是正确的默认配置通常是假定为parent-last。您应该澄清在这种情况下类加载行为是不同的,因为这就是混淆OP的原因。在“正常”java应用程序中,子类加载器中包含的重复类将被忽略。最后如何设置父类的配置?关于编辑。事实上,我曾经尝试过类加载器java2ClassLoadingCompliance,但是由于这个原因,我在记录器配置方面出现了一个新的错误。最后,最好在我的应用程序中使用jboss默认组件