开发大量基于XML的Java应用程序,最近我在Ubuntu Linux上遇到了一个有趣的问题。
我的应用程序使用Java插件框架,似乎无法将dom4j创建的XML文档转换为Batik的 SVG规范实现。
在控制台上,我知道发生了一个错误:
线程“AWT-EventQueue-0”中的异常java.lang.LinkageError:接口中的加载器约束违规itable初始化:何时解析方法“org.apache.batik.dom.svg.SVGOMDocument.createAttribute(Ljava / lang / String;)Lorg / W3C / DOM /的Attr;” 当前类的类加载器(org / java / plugin / standard / StandardPluginClassLoader的实例)org / apache / batik / dom / svg / SVGOMDocument,以及接口org / w3c的类加载器(<bootloader>的实例)对于签名中使用的org / w3c / dom / Attr类型,dom / Document具有不同的Class对象
在org.apache.batik.dom.svg.SVGDOMImplementation.createDocument(SVGDOMImplementation.java:149)
在org.dom4j.io.DOMWriter.createDomDocument(DOMWriter.java:361)
在org.dom4j.io.DOMWriter.write(DOMWriter.java:138)
我认为这个问题是由JVM的原始类加载器和插件框架部署的类加载器之间的冲突引起的。
据我所知,不可能为要使用的框架指定一个类加载器。它可能被破解,但我宁愿采取一种不那么积极的方法来解决这个问题,因为(无论出于何种原因)它只发生在Linux系统上。
您有没有遇到过这样的问题,并且有任何想法如何解决这个问题,或者至少能够解决问题的核心问题?
发布于 2018-03-29 15:27:59
LinkageError是你在一个经典的案例中得到的,你有一个类C被多个类加载器加载,并且这些类在相同的代码中被使用(比较,转换等)。无论它是否是相同的Class名称,或者即使它是从相同的jar中加载也没关系 - 如果从另一个类加载器加载,则来自一个classloader的Class始终被视为不同的Class。
这个消息(这些年来有所改善)说:
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
所以,这里的问题在于解决使用org.w3c.dom.Attr(标准DOM库的一部分)的SVGOMDocument.createAttribute()方法。但是,加载Batik的Attr版本是从不同的类加载器加载的,而不是您传递给该方法的Attr实例。
您会看到Batik的版本似乎是从Java插件加载的。而你的是从“”加载的,这很可能是内置JVM加载器之一(引导类路径,ESOM或类路径)。
三个突出的类加载器模型是:
我不知道JPF类加载器使用了什么委派策略,但关键是您希望加载一个版本的dom库,并且每个人都可以从同一位置获取该类。这可能意味着将其从类路径中移除并作为插件加载,或者阻止蜡染加载它或其他东西。
发布于 2018-03-29 16:26:15
听起来像一个类加载器层次结构问题。我无法确定应用程序的部署环境是什么类型,但有时候这种问题可能发生在Web环境中 - 应用程序服务器在其中创建类加载程序的层次结构,类似于以下内容:
javahome / lib - 作为根 appserver / lib - 作为根 webapp / WEB-INF / lib的子节点 - 作为根子节点的子节点 等
通常,类加载器将加载委托给它们的父类加载器(这称为“ parent-first
”),如果该类加载器找不到该类,则子类加载器将尝试执行。例如,如果在webapp / WEB-INF / lib中部署为JAR的类尝试加载类,则首先会要求与appserver / lib对应的类加载器加载该类(然后请求与javahome / lib相对应的类加载器加载类),如果查找失败,则搜索WEB-INF / lib以匹配此类。
在Web环境中,您可能遇到此层次结构的问题。例如,之前遇到的一个错误/问题是,WEB-INF / lib中的类取决于部署在appserver / lib中的类,而该类又取决于部署在WEB-INF / lib中的类。这导致失败,因为虽然类加载器能够委派给父类加载器,但他们不能将其委托回树中。因此,WEB-INF / lib类加载器会向appserver / lib类加载器请求一个类,appserver / lib类加载器将加载该类并尝试加载相关类,并失败,因为它无法在appserver / lib或javahome中找到该类/ lib目录下。
因此,虽然您可能未在Web /应用程序服务器环境中部署您的应用程序,但如果您的环境设置了类加载程序的层次结构,则我的太长解释可能适用于您。可以?JPF是否能够实现某种类型的加载器魔法来实现它的插件功能?
https://stackoverflow.com/questions/-100007861
复制相似问题