WAS 6.1 java.lang.VerifyError:违反了类加载约束

时间:2010-05-18 23:11:49

标签: java websphere classloader verifyerror

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的副本,与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'的唯一其他实例 我可以找到(除了我们的应用程序部署的副本)在目录中 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的版本 首先是“。这看起来与我们实际看到的情况相反。

问题:

类加载器委托设置如何与上述信息交互以产生观察到的行为?

5 个答案:

答案 0 :(得分: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。

有两种解决方案:

  1. 从应用程序中删除所有API jar,并使用JDK中的API jar。例如,删除包含org.xml.sax或org.w3c.dom的jar。
  2. 在WAR中包含引用要引用的类的所有库。例如,在WAR中包含JAXB库的副本。
  3. 根据我的经验,链接错误很难追踪,因为JVM提供了关于导致链接添加的原因的糟糕信息。我通常启用类加载器跟踪,重现问题,然后向后走,直到我发现从应用程序外部加载的类“听起来像”它可能引用已知存在于应用程序内的类。

答案 1 :(得分:0)

我们的问题是在WAS 8.5上部署。

在我们的Web应用程序中,我们有一个由cxf生成的Web服务客户端。没问题。

当我们在tika-parser中添加mime类型检测时,我们就遇到了这个问题。

我们排除了三个依赖项:

<dependency>
            <groupId>org.apache.tika</groupId>
            <artifactId>tika-parsers</artifactId>
            <version>${apache.tika.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>geronimo-stax-api_1.0_spec</artifactId>
                    <groupId>org.apache.geronimo.specs</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>xercesImpl</artifactId>
                    <groupId>xerces</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>xmlbeans</artifactId>
                    <groupId>org.apache.xmlbeans</groupId>
                </exclusion>
            </exclusions>
        </dependency>

一旦排除它们,我们的应用程序就会成功启动。

答案 2 :(得分:0)

可能为时已晚,但我们解决了这个问题,在server.xml中删除了这一行:

JAXB-2.1

答案 3 :(得分:-1)

禁用字节码验证

java.lang.VerifyError - 运行时未经检查的异常 一旦在Websphere JVM中加载了类文件,那么字节码变换就是下一个过程。如果我们的类违反了JVM约束,那么字节码验证就会出现,那么就会出现这个错误。

禁用字节码验证。转到

管理控制台-> server1 -> java和进程管理->process definition-> JVM参数`

在JVM参数中传递以下字符串

 -Xverify:none 

并在工作区中打开ApplicationDeploymentDescriptor xml文件,转到部署选项卡,选择PARENT_LAST for war,以及第一个选项。这会停止xml验证错误。

答案 4 :(得分:-2)

  

如果我们改为“父类加载器   首先“我们没有看到例外。   这与预期相反   行为。

是的,这是正确的,这是你能看到这种行为的唯一方法。我建议你看看“你真的得到班级装载机吗?”谈话,因为你的问题没有单一或简短的答案。

http://www.slideshare.net/guestd56374/do-you-really-get-class-loaders http://www.parleys.com/#sl=2&st=5&id=1585