环境是 Linux 上的 WAS 6.1,部署了一个使用来自 xercesImpl.jar 的类的 web 应用程序。
由于公司政策限制,必须使用以下设置部署应用程序:
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 并且仍然得到相同的错误(不是 ClassNotFoundException)。因此,WAS 似乎正在使用它自己的副本来解析引用,该副本与我们编译的类文件中的引用不兼容。但是,我能找到的唯一其他“xercesImpl.jar”实例(与我们的应用程序一起部署的副本除外)位于 directory
deploytool
中,这似乎在应用程序服务器之外。
我扫描了 WAS 中的所有罐子(全部 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 的版本。这似乎与我们实际看到的相反。
问题:
类加载器委托设置如何与上述信息交互以产生观察到的行为?