代码之家  ›  专栏  ›  技术社区  ›  Jim Garrison

was 6.1 java.lang.verifyError:违反类加载约束

  •  10
  • Jim Garrison  · 技术社区  · 15 年前

    Linux上的环境是6.1,部署了一个使用 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;)
    

    到目前为止的分析

    它似乎提供了 org.apache.xerces.jaxp.documentbuilderimpl,因为我们可以删除 从war文件中获取xercesimpl.jar,仍然会得到相同的错误(不是 ClassNotFoundException)。因此似乎是在解决参考文献 使用与我们的 编译的类文件。但是,“xercesimpl.jar”的唯一其他实例 我可以发现(除了我们的应用程序部署的副本)在目录中 deploytool 似乎在应用服务器之外。

    我扫描了里面所有的罐子(总共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.* , 所以这很可能是类加载器解析引用的地方。

    奇怪的是:

    如果我们改为“父类加载器优先”,则不会看到异常。 这与预期的行为背道而驰。我们希望 “application classloader first”它将使用我们 提供,并且仅当我们设置“父类加载器”时才使用was的版本 第一。这似乎与我们实际看到的情况相反。

    问题:

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

    5 回复  |  直到 7 年前
        1
  •  14
  •   Brett Kail    15 年前

    您的war还包括org.xml.sax或org.w3c.dom类,然后您引用了应用程序外部的类,该类也引用了这些类。这将设置一个场景,其中应用程序类加载器对同一类的两个实例具有可见性,这是一个链接错误。

    例如,如果应用程序使用javax.xml.bind.unmarshaller.unmarshall(inputsource),那么将从JDK加载unmarshaller,并且unmarshaller类只对JDK inputsource具有可见性。当应用程序创建其inputsource时,它将从war加载类(因为“app first”策略),然后应用程序将尝试将war inputsource的实例传递给jdk unmarshaller,后者只能接受jdk inputsource的实例。

    有两种解决方案:

    1. 从应用程序中删除所有api jar,并使用jdk中的jar。例如,删除包含org.xml.sax或org.w3c.dom的jar。
    2. 包括战争中引用要引用的类的所有库。例如,在您的战争中包含JAXB库的副本。

    根据我的经验,链接错误很难被跟踪,因为JVM提供了关于什么导致添加链接的糟糕信息。我通常启用类加载器跟踪,重现问题,然后向后走,直到找到一个从应用程序外部加载的类,“听起来像”它可能引用了一个已知存在于应用程序内部的类。

        2
  •  0
  •   shane lee    10 年前

    我们的问题发生在8.5。

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

    当我们在tika解析器中添加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>
    

    一旦它们被排除在外,我们的应用程序就成功启动了。

        3
  •  0
  •   Eduardo Arcentales    7 年前

    可能太迟了,但我们解决了这个问题,在server.xml中删除了这一行:

    JAXB-2.1

        4
  •  -1
  •   Community CDub    10 年前

    禁用字节码验证

    java.lang.verify错误- 运行时未选中异常 一旦类文件加载到WebSphere JVM中,那么字节代码变量化就是下一个过程。在字节代码验证期间,如果我们的类违反了JVM约束,那么就会出现此错误。

    禁用字节码验证。去

    管理控制台 -> 服务器1 -gt; Java与过程管理 ->process definition-> JVM参数

    在jvm中,参数传递以下字符串

     -Xverify:none 
    

    在工作区中打开applicationDeploymentDescriptor XML文件,转到Deployment选项卡,选择Parent_Last for War,以及第一个选项。这将停止XML验证错误。

        5
  •  -2
  •   Jevgeni Kabanov    15 年前

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

    是的,没错,这是你看到这种行为的唯一途径。我可以建议你看一下“你真的有班级装载机吗?”谈谈,因为你的问题没有一个简单的答案。

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