在开发一个高度基于 XML 的 Java 应用程序时,我最近在 Ubuntu Linux 上遇到了一个有趣的问题。
我的应用程序,使用Java插件框架,似乎无法转换dom4j- 创建 XML 文档Batik'sSVG 规范的实现。
在控制台上,我得知发生了错误:
Exception in thread "AWT-EventQueue-0" java.lang.LinkageError: loader constraint violation in interface itable initialization: when resolving method "org.apache.batik.dom.svg.SVGOMDocument.createAttribute(Ljava/lang/String;)Lorg/w3c/dom/Attr;" the class loader (instance of org/java/plugin/standard/StandardPluginClassLoader) of the current class, org/apache/batik/dom/svg/SVGOMDocument, and the class loader (instance of <bootloader>) for interface org/w3c/dom/Document have different Class objects for the type org/w3c/dom/Attr used in the signature
at org.apache.batik.dom.svg.SVGDOMImplementation.createDocument(SVGDOMImplementation.java:149)
at org.dom4j.io.DOMWriter.createDomDocument(DOMWriter.java:361)
at org.dom4j.io.DOMWriter.write(DOMWriter.java:138)
我认为该问题是由 JVM 的原始类加载器与插件框架部署的类加载器之间的冲突引起的。
据我所知,不可能指定框架使用的类加载器。也许可以破解它,但我更喜欢采用不太激进的方法来解决这个问题,因为(无论出于何种原因)它只发生在 Linux 系统上。
你们中是否有人遇到过这样的问题,并且知道如何解决它或至少找到问题的核心?
LinkageError 是一种经典情况,其中您有一个由多个类加载器加载的类 C,并且这些类在同一代码中一起使用(比较、强制转换等),您会遇到这种情况。如果它是相同的类名,或者即使它是从相同的 jar 加载的,也没关系 - 如果从另一个类加载器加载,来自一个类加载器的类始终被视为不同的类。
该消息(多年来已经有了很大改进)说:
Exception in thread "AWT-EventQueue-0" java.lang.LinkageError:
loader constraint violation in interface itable initialization:
when resolving method "org.apache.batik.dom.svg.SVGOMDocument.createAttribute(Ljava/lang/String;)Lorg/w3c/dom/Attr;"
the class loader (instance of org/java/plugin/standard/StandardPluginClassLoader)
of the current class, org/apache/batik/dom/svg/SVGOMDocument,
and the class loader (instance of ) for interface org/w3c/dom/Document
have different Class objects for the type org/w3c/dom/Attr used in the signature
因此,这里的问题在于解决 SVGOMDocument.createAttribute() 方法,该方法使用 org.w3c.dom.Attr (标准 DOM 库的一部分)。但是,使用 Batik 加载的 Attr 版本是从与传递给该方法的 Attr 实例不同的类加载器加载的。
您会看到 Batik 的版本似乎是从 Java 插件加载的。您的加载器是从“”加载的,它很可能是内置 JVM 加载器之一(引导类路径、ESOM 或类路径)。
三个著名的类加载器模型是:
- 委托(JDK 中的默认设置 - 先询问父母,然后询问我)
- 委托后(常见于插件、servlet 和您想要隔离的地方 - 先问我,然后问家长)
- 兄弟(常见于 OSGi、Eclipse 等依赖模型中)
我不知道 JPF 类加载器使用什么委托策略,但关键是您希望加载一个版本的 dom 库,并且每个人都从同一位置获取该类。这可能意味着将其从类路径中删除并作为插件加载,或者阻止 Batik 加载它,或者其他什么。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)