当前位置: 首页 > 面试题库 >

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

钮高朗
2023-03-14
问题内容

我的申请有问题。要恢复该问题,我必须将应用程序从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

经过多次搜索后,我发现此错误在这里,因为我多次在同一个包中找到同一个类。曾经在一个依赖包中(来自我的pom.xml),一次是由jboss提供的。

因此,为解决此问题,我为依赖项提供了一个“提供”的范围。

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

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

感谢您的解释:)


问题答案:

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

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

Bootstrap ClassLoader->系统类加载器-> JBoss系统类加载器-> Ear Class Loader-> War Class
Loader。

战争类装载者的父母是耳朵类装载者,依此类推。

现在,如果Bootstrap ClasssLoader加载了jar A,并且耳朵也与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之类的系统类。在您的错误中,看起来好像javax
/ xml / datatype / DatatypeConstants被加载到org / jboss / classloader / spi / base
/ BaseClassLoader中。让我们假设EAR类加载器(或WAR)。一个快速的谷歌显示它是xml-apis家族的一部分,并且可能是jaxp-api。

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

您可以想像这是不可能发生的。实际上看起来您有双亲。因为从JBoss类加载机制中加载类时,如果启用了父级优先,则初始DatatypeConstants将返回父级(引导)的DatatypeConstants而不是子级。因此,正如jtahlborn指出的那样,您希望此处的孩子的类加载器被忽略。

就解决方案而言,除非出于特定原因需要依赖项(例如比当前版本更好的更新版本),否则我将委托给jboss的实现。如果不是这种情况,您可以看一下class- loading java2ClassLoadingCompliancejbosshtml" target="_blank">配置中包含的元素。



 类似资料:
  • 本文向大家介绍Java类加载器和类加载机制实例分析,包括了Java类加载器和类加载机制实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Java类加载器和类加载机制。分享给大家供大家参考,具体如下: 一 点睛 1 类加载器负责将.class文件(可能在磁盘上,也可能在网络上)加载到内存中,并为之生成对应的java.lang.Class对象。 2 当JVM启动时,会形成由三个类加载器组

  • 另外,如果我将instance设置为null,那么这两个类是否都设置为null?

  • 问题内容: 例如我有静态字段的类: 我可以使用两个不同的类加载器两次加载该类。我该如何避免呢?这是不安全和危险的。 另外,如果我将instance设置为null,那么是否将两个类的instance都设置为null? 问题答案: 如果你希望跨类加载器为true ,则需要一个公共父类来加载所讨论的类,或者你需要自己指定类加载器。 更新:来自@Pshemo的评论下面的博客中相当一部分内容可能直接来自Ja

  • 我有一个类,它实现了接口。类由system classloader加载,接口在第三方组件中定义,我认为第三方组件将接口加载到另一个类加载器(动态类加载器)中。 当我试图创建的新实例时,我得到的是的。我想这是因为它是由不同的类加载器加载的。 我尝试创建(与Guice使用的类似),然后从system类加载器加载类,并从另一个类加载器加载所有其他类,我认为这是用于的类加载器,但没有成功。 有办法绕过它吗

  • 框架中所有的类都是通过类加载器(ClassLoader)加载的,通过Loader我们可以实现类的统一管理。下面我们一起来看看Loader提供了哪些加载方法: 1. Loader::import 加载一个类或者加载一个包 方法原型 import( $classPath, $type = IMPORT_APP, $extension=EXT_PHP ) 参数名称 参数说明 $classPath 文件的

  • 加载器,顾名思义,是用于加载元素的,加载的元素可以是库(类),视图文件 , 驱动器 ,辅助函数 , 模型 或其他你自己的文件。 注解 该类由系统自动加载,你无需手工加载。 应用程序"包" 包的视图文件 类参考 应用程序"包" 应用程序包(Package)可以很便捷的将你的应用部署在一个独立的目录中, 以实现自己整套的类库,模型,辅助函数,配置,文件和语言包。 建议将这些应用程序包放置在 appli