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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2861807/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 13:49:36  来源:igfitidea点击:

WAS 6.1 java.lang.VerifyError: class loading constraint violated

javawebsphereclassloaderverifyerror

提问by Jim Garrison

The environment is WAS 6.1 on Linux, deploying a webapp that uses classes from xercesImpl.jar.

环境是 Linux 上的 WAS 6.1,部署了一个使用来自 xercesImpl.jar 的类的 web 应用程序。

Due to company policy restrictions, the app must be deployed with settings:

由于公司政策限制,必须使用以下设置部署应用程序:

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

The WAR file contains a copy of xercesImpl.jar, the same one that was in the classpath when the app was compiled.

WAR 文件包含 xercesImpl.jar 的副本,该副本与编译应用程序时位于类路径中的副本相同。

When launching the webapp, when Spring tries to parse its configs, it throws:

启动 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;)

ANALYSIS SO FAR

到目前为止的分析

It appears that WAS provides an implementation of org.apache.xerces.jaxp.DocumentBuilderImpl, because we can remove xercesImpl.jar from the WAR file and still get the same error (not ClassNotFoundException). Thus WAS seems to be resolving the references using its own copy that is incompatible with the references in our compiled class files. However, the only other instance of 'xercesImpl.jar' I can find (other than the copy deployed with our app) is in directory deploytool, which seems to be outside the app server.

似乎 WAS 提供了 org.apache.xerces.jaxp.DocumentBuilderImpl 的实现,因为我们可以从 WAR 文件中删除 xercesImpl.jar 并且仍然得到相同的错误(不是 ClassNotFoundException)。因此,WAS 似乎正在使用自己的副本解析引用,该副本与我们编译的类文件中的引用不兼容。但是,我能找到的唯一另一个 'xercesImpl.jar' 实例(除了与我们的应用程序一起部署的副本)在 directory 中 deploytool,它似乎在应用程序服务器之外。

I scanned all the jars in WAS (all 1300 of them) with

我扫描了 WAS 中的所有罐子(全部 1300 个)

for i in `find . -name \*.jar`; do jar tvf $i|grep -qi xerces && echo $i ; done

and found that ./java/jre/lib/xml.jarcontains all the classes in org.apache.xerces.*, so this is likely where the classloader is resolving the reference.

并发现它./java/jre/lib/xml.jar包含 中的所有类org.apache.xerces.*,因此这很可能是类加载器解析引用的地方。

HERE'S THE WEIRD PART:

这是奇怪的部分:

If we change to "parent class loader first" we do not see the exception. This goes counter to the expected behavior. We would expect that with "application classloader first" it would use the xercesImpl.jar that we provided, and use WAS's version only if we set "parent classloader first". This appears to be backwards from what we actually see.

如果我们更改为“先加载父类加载器”,我们将看不到异常。这与预期的行为背道而驰。我们期望“应用程序类加载器优先”将使用我们提供的 xercesImpl.jar,并且仅当我们设置“父类加载器优先”时才使用 WAS 的版本。这似乎与我们实际看到的相反。

THE QUESTION:

问题:

How is the classloader delegation setting interacting with the above information to result in the observed behavior?

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

采纳答案by Brett Kail

Your WAR is also including either org.xml.sax or org.w3c.dom classes, and then you're referencing a class that is outside your application that also references these classes. This sets up a scenario where your application class loader has visibility to two instances of the same class, which is a linkage error.

您的 WAR 还包括 org.xml.sax 或 org.w3c.dom 类,然后您引用了应用程序外部的类,该类也引用了这些类。这会设置一个场景,您的应用程序类加载器可以看到同一个类的两个实例,这是一个链接错误。

For example, if your application uses javax.xml.bind.Unmarshaller.unmarshal(InputSource), then Unmarshaller would be loaded from the JDK, and the Unmarshaller class only has visibility to the JDK InputSource. When your application creates its InputSource, it will load the class from the WAR (because "app first" policy), and then your application would attempt to pass an instance of the WAR InputSource to the JDK Unmarshaller, which can only accept an instance of the JDK InputSource.

例如,如果您的应用程序使用 javax.xml.bind.Unmarshaller.unmarshal(InputSource),则 Unmarshaller 将从 JDK 加载,并且 Unmarshaller 类仅对 JDK InputSource 具有可见性。当您的应用程序创建其 InputSource 时,它​​将从 WAR 加载类(因为“应用优先”策略),然后您的应用程序将尝试将 WAR InputSource 的实例传递给 JDK Unmarshaller,后者只能接受JDK 输入源。

There are two solutions:

有两种解决方案:

  1. Remove all API jars from your application, and use the ones from the JDK. For example, remove the jar containing org.xml.sax or org.w3c.dom.
  2. Include all libraries in your WAR that reference the classes you want to reference. For example, include a copy of the JAXB library in your WAR.
  1. 从应用程序中删除所有 API jar,并使用 JDK 中的那些。例如,删除包含 org.xml.sax 或 org.w3c.dom 的 jar。
  2. 在您的 WAR 中包含所有引用您要引用的类的库。例如,在您的 WAR 中包含 JAXB 库的副本。

In my experience, linkage errors are quite difficult to track down because JVMs give lousy information about what causes linkages to be added. I usually enable class loader trace, reproduce the problem, and then walk backwards until I find a class loaded from outside the application that "sounds like" it might reference a class that is known to exist inside the application.

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

回答by Jevgeni Kabanov

If we change to "parent class loader first" we do not see the exception. This goes counter to the expected behavior.

如果我们更改为“先加载父类加载器”,我们将看不到异常。这与预期的行为背道而驰。

Yes, that's correct, it's the only way you can see such behaviour. I can suggest you yo take a look at the "Do you really get class loaders?" talk, as there is no single or short answer to your question.

是的,这是正确的,这是您可以看到此类行为的唯一方式。我可以建议你看看“你真的有类加载器吗?” 谈谈,因为您的问题没有单一或简短的答案。

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

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

回答by shane lee

Our issue was deploying on WAS 8.5.

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

In our web application we have a web service client generated by cxf. No issues.

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

When we added in tika-parser for mime type detection, then we got this issue.

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

We excluded three dependencies:

我们排除了三个依赖项:

<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>

Once they were excluded, our application started successfully.

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

回答by Neelam Chahal

Disable the Bytecode Verification

禁用字节码验证

java.lang.VerifyError - Runtime Unchecked Exception once class file is loaded in Websphere JVM, then byte code varification is the next process.during byte code verification if our class in violating the JVM constraints ,then this error appears.

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

disable bytecode verification. Go to

禁用字节码验证。去

admin console->server1->java and process management->process definition->JVM arguments`

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

And in JVM arguments pass the following string

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

 -Xverify:none 

and in workspace open the ApplicationDeploymentDescriptor xml file, go to deployment tab, select PARENT_LAST for war, as well as for first option. this stops the xml validations errors.

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

回答by Eduardo Arcentales

May be it's too late but, we solved this problem, removing this line in server.xml:

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

jaxb-2.1

jaxb-2.1