2011-04-12 48 views
3

我的应用程序出现问题。要恢复这个问题,我不得不这样做从JBoss的4应用程序迁移到JBoss 5Jboss 5,类加载器和多个类实例

战争期间deployement,我有这个错误:

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 

许多searchs之后,我发现这个错误在这里因为我有几次在不同的套餐中上过同一堂课。一旦进入一个依赖包(从我的pom.xml)并且一旦由jboss提供。

所以,要解决这个问题,我已经为我的依赖提供了一个“提供”范围。

但我不明白为什么这个解决方案有效。我认为它可以在应用程序中使用同一个类的几次。我知道这不是一件好事,但使用jboss 4,这是工作。

有人可以解释我为什么它的工作原理与JBoss 4,而不是与JBoss 5

感谢您的解释:)

+1

什么是重复的类?它重复使用哪些软件包? – 2013-02-22 16:19:54

+0

你在哪里设置提供,谢谢 – 2017-01-09 16:28:40

回答

8

你们看到的是一个应用服务器的负载JBoss的库和效果在不同的类加载器

EAR库

你可以把类似的(但不一定是)一个EAR的类加载器层次结构的:

引导类加载器 - >系统类加载器 - > JBoss的系统类加载器 - > EA r Class Loader - > War Class Loader。

其中war class loader的父级是ear class loader等等。

现在,如果Bootstrap ClasssLoader有一个jar被加载并且耳朵也被部署到jar A中,Bootstrap Class Lodaer和Ear Class Loader将在同一个类加载器中创建两次相同的类。

我会假设(并非100%确定)JBoss 4没有与javax/xml/namespace/QName捆绑在一起。如果那是真的,JBoss 5更可能是Java的不同的升级版本(4 - > 5或5 - > 6)。因此(使用新的JBoss 5),当您尝试将javax/xml/namespace/QName传递给您的某个类时,它期望从耳朵中得到类。但是,由于类加载器首选项(父级第一等等),您将从Bootstrap类加载器中为其提供QName类。

由于类类型相同,但类实例不等于你的LinkageError类

编辑:

只有两个地址的两点意见 -

提到的类装载行为jtahlborn是完全不同。在正常的应用程序中,类似于QName的系统类将在引导类加载器中一直寻找。在你的错误中,它看起来好像在org/jboss/classloader/spi/base/BaseClassLoader中加载了javax/xml/datatype/DatatypeConstants。让我们假设EAR类加载器(或WAR)。快速谷歌显示,这是xml-apis家族的一部分,也可能是jaxp-api。

因此,在您的代码中的某处(或位于EAR的类加载器中的其他库代码)需要DatatypeConstants - 强制在EAR的类加载器中查找类。 QName对象的创建虽然从引导类加载器(而不是EAR)中加载类。如果QName类已被系统初始化,它可能会发生这种情况。

这正如你所想象的那样,并不是假设发生。它实际上看起来像你有父母最后。因为当从JBoss类加载机制加载类时,如果父代先启用了,则初始DatatypeConstants将返回父代(引导程序)DatatypeConstants而不是子代。所以jtahlborn指出你会希望孩子们的classloader在这里被忽略。

就解决方案而言,除非您需要某个特定原因的依赖关系(比如稍微更新的版本比当前更好),否则我将委托给jboss的实现。如果不是这种情况,您可以查看jboss配置所具有的class-loading java2ClassLoadingCompliance元素。

+0

我认为这是接近,但不完全正确。一般来说,战争类装入器被设置为喜欢从孩子加载。否则,你永远不会看到冲突,因为战争中的类的版本将被忽略。你是对的,最有可能的问题是java版本的差异(我怀疑jboss包含jaxb类)。 – jtahlborn 2011-04-12 16:20:26

+0

我在将websphere和weblogic升级到较新版本(包括较新版本的Java)时所学到的是,java运行时包含它自己的javax/xml/namespace/QName和相关库。这是我认为是OP的问题。是的,你是正确的默认配置通常是假设父母最后一次。 – 2011-04-12 16:22:34

+0

你应该澄清,在这种情况下类加载行为是_different_,因为这是混淆OP。在“普通”Java应用程序中,子类加载器中包含的重复类将被忽略。 – jtahlborn 2011-04-12 16:27:28

1

-verbose:class在虚拟机参数将给出如何加载类。 如果有重复,您可以删除冲突的罐子/罐子。

0

谢谢你的解释 - 这是非常有帮助的。

我知道这个问题与JBoss 5.0.0版本中修复的bug有关。但即使我运行的是旧版本的JBoss,但我仍然遇到了这个错误。 无论如何,我做了大量的研究并运行maven依赖关系树几次,以查看重复定义来自哪里。我终于可以通过添加两个依赖项来解决这个错误 - 提供的作用域被设置为 - 我的主要文件夹:
(sun.jaxb-impl 2.1,javax.jaxb-api 2.2)我希望这些信息可以帮助某人。