Jim*_*son 10 java websphere classloader verifyerror
环境是Linux上的WAS 6.1,部署了一个使用xercesImpl.jar类的webapp.
由于公司政策限制,必须使用以下设置部署应用:
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
Run Code Online (Sandbox Code Playgroud)
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;)
Run Code Online (Sandbox Code Playgroud)
因此分析
看来WAS提供了org.apache.xerces.jaxp.DocumentBuilderImpl的实现,因为我们可以从WAR文件中删除xercesImpl.jar并仍然得到相同的错误(不是ClassNotFoundException).因此,WAS似乎使用自己的副本来解析引用,该副本与我们编译的类文件中的引用不兼容.但是,我能找到的'xercesImpl.jar'的唯一其他实例(除了使用我们的应用程序部署的副本)位于目录中
deploytool,这似乎在应用服务器之外.
我用WAS(所有1300个)扫描了所有的罐子
for i in `find . -name \*.jar`; do jar tvf $i|grep -qi xerces && echo $i ; done
Run Code Online (Sandbox Code Playgroud)
并发现它./java/jre/lib/xml.jar包含所有类org.apache.xerces.*,因此这可能是类加载器解析引用的地方.
这是肮脏的部分:
如果我们改为"父类加载器第一",我们看不到异常.这与预期的行为背道而驰.我们希望使用"application classloader first",它将使用我们提供的xercesImpl.jar,并且只有在我们设置"父类加载器优先"时才使用WAS的版本.这看起来与我们实际看到的情况相反.
问题:
类加载器委托设置如何与上述信息交互以产生观察到的行为?
Bre*_*ail 14
您的WAR还包括org.xml.sax或org.w3c.dom类,然后您引用的应用程序之外的类也引用了这些类.这将设置一个场景,您的应用程序类加载器可以看到同一个类的两个实例,这是一个链接错误.
例如,如果您的应用程序使用javax.xml.bind.Unmarshaller.unmarshal(InputSource),那么将从JDK加载Unmarshaller,而Unmarshaller类只能看到JDK InputSource.当您的应用程序创建其InputSource时,它将从WAR加载类(因为"app first"策略),然后您的应用程序将尝试将WAR InputSource的实例传递给JDK Unmarshaller,它只接受一个实例JDK InputSource.
有两种解决方案:
根据我的经验,链接错误很难追踪,因为JVM提供了关于导致链接添加的原因的糟糕信息.我通常启用类加载器跟踪,重现问题,然后向后走,直到我发现从应用程序外部加载的类"听起来像"它可能引用已知存在于应用程序内的类.