Jboss 5,类加载器和多个类实例

Kiv*_*iva 3 java jboss dependencies

我的申请有问题.要恢复这个问题,我必须将应用程序从jboss 4迁移到jboss 5.

在战争部署期间,我遇到了这个错误:

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
Run Code Online (Sandbox Code Playgroud)

经过多次搜索后,我发现这个错误在这里是因为我在不同的包中有过几次相同的类.一旦进入依赖包(来自我的pom.xml)并且一次由jboss提供.

因此,为了解决这个问题,我为我的依赖项提供了"提供"范围.

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

有人可以解释为什么它适用于jboss 4而不适用于jboss 5.

谢谢你的解释:)

Joh*_*int 8

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

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

Bootstrap ClassLoader - > System Class Loader - > JBoss System Class Loader - > Ear Class Loader - > War Class Loader.

war类加载器的父级是ear类加载器等等.

现在,如果Bootstrap ClasssLoader加载了jar A并且还使用jar A部署了ear,则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的类加载器中查找类.虽然从引导类加载器(而不是EAR)加载了类,但是创建了QName对象.如果QName类已经被系统初始化了,那么就会发生这种情况.

你可以想象这不会发生.它实际上看起来像你有父母的最后一个.因为在从JBoss类加载机制加载类时,如果已启用parent-first,则初始DatatypeConstants将返回父级(bootstrap)DatatypeConstants而不是childs.因此,jtahlborn指出,你会希望忽略孩子们在这里的类加载器.

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