环境是Linux上的WAS 6.1,部署一个webapp,使用 来自 xercesImpl.jar 的类。
由于公司政策限制,应用程序必须与 设置:
Class Loader Order
Classes loaded with parent class loader first
-> Classes loaded with application class loader first
WAR class loader policy
Class loader for each WAR file in application
-> Single class loader for application
WAR 文件包含 xercesImpl.jar 的副本,与 编译应用程序时在类路径中。
启动 webapp 时,当 Spring 尝试解析它的配置时,它 抛出:
java.lang.VerifyError: class loading constraint violated
(class: org/apache/xerces/jaxp/DocumentBuilderImpl
method: parse(Lorg/xml/sax/InputSource;)Lorg/w3c/dom/Document;)
到目前为止的分析
WAS 似乎提供了一个实现
org.apache.xerces.jaxp.DocumentBuilderImpl,因为我们可以删除
来自 WAR 文件的 xercesImpl.jar 仍然得到相同的错误(不是
类未发现异常)。因此 WAS 似乎正在解析引用
使用与我们的引用文献不兼容的自己的副本
编译的类文件。但是,“xercesImpl.jar”的唯一其他实例
我可以找到(除了我们的应用程序部署的副本)在目录中
deploytool
,似乎在应用服务器之外。
我扫描了 WAS 中的所有 jar (全部 1300 个)
for i in `find . -name \*.jar`; do jar tvf $i|grep -qi xerces && echo $i ; done
发现./java/jre/lib/xml.jar
包含org.apache.xerces.*
中的所有类,
所以这很可能是类加载器解析引用的地方。
这是奇怪的部分:
如果我们改为“父类加载器优先”,我们看不到异常。 这与预期的行为背道而驰。我们希望与 “首先应用程序类加载器”它将使用我们的 xercesImpl.jar 提供,并且仅当我们设置“父类加载器”时才使用 WAS 的版本 首先”。这似乎与我们实际看到的相反。
问题:
类加载器委派设置如何与上述信息交互以导致观察到的行为?
最佳答案
您的 WAR 还包括 org.xml.sax 或 org.w3c.dom 类,然后您引用了一个在您的应用程序之外的类,该类也引用了这些类。这设置了一个场景,您的应用程序类加载器可以看到同一类的两个实例,这是一个链接错误。
例如,如果您的应用程序使用 javax.xml.bind.Unmarshaller.unmarshal(InputSource),那么 Unmarshaller 将从 JDK 加载,并且 Unmarshaller 类仅对 JDK InputSource 可见。当您的应用程序创建其 InputSource 时,它将从 WAR 加载该类(因为“应用程序优先”策略),然后您的应用程序将尝试将 WAR InputSource 的实例传递给 JDK Unmarshaller,它只能接受一个实例JDK 输入源。
有两种解决方法:
- 从您的应用程序中删除所有 API jar,并使用 JDK 中的那些。例如,删除包含 org.xml.sax 或 org.w3c.dom 的 jar。
- 在您的 WAR 中包含引用您要引用的类的所有库。例如,在您的 WAR 中包含 JAXB 库的副本。
根据我的经验,链接错误很难追踪,因为 JVM 提供了有关导致添加链接的原因的糟糕信息。我通常启用类加载器跟踪,重现问题,然后向后走,直到我找到从应用程序外部加载的类,“听起来”它可能引用已知存在于应用程序内部的类。
关于java - 是 6.1 java.lang.VerifyError : class loading constraint violated,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2861807/