WAS 6.1 java.lang.VerifyError:违反了类加载约束 [英] WAS 6.1 java.lang.VerifyError: class loading constraint violated

查看:375
本文介绍了WAS 6.1 java.lang.VerifyError:违反了类加载约束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

环境是Linux上的WAS 6.1,部署了一个使用xercesImpl.jar中
类的webapp。

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

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

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

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

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

启动webapp时,当Spring尝试解析其配置时,
抛出:

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

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的实现,因为我们可以删除$ b $来自WAR文件的b xercesImpl.jar仍然得到相同的错误(不是
ClassNotFoundException)。因此,WAS似乎使用自己的副本来解析引用
,该副本与我们的
编译的类文件中的引用不兼容。但是,我能找到的'xercesImpl.jar'
的唯一其他实例(除了使用我们的应用程序部署的副本)位于目录
deploytool ,这似乎是在应用服务器之外。

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(所有1300个)扫描了所有的罐子

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

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

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

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

这里是WEIRD PART:

HERE'S THE WEIRD PART:

如果我们改为父类加载器优先,我们看不到异常。
这与预期的行为背道而驰。我们希望使用
应用程序类加载器优先,它将使用我们提供的
的xercesImpl.jar,并且只有在我们设置parent classloader
first时才使用WAS的版本。这看起来与我们实际看到的情况相反。

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.

问题:

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

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

推荐答案

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

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.

例如,如果您的应用程序使用javax。 xml.bind.Unmarshaller.unmarshal(InputSource),然后将从JDK加载Unmarshaller,而Unmarshaller类只能看到JDK InputSource。当您的应用程序创建其InputSource时,它将从WAR加载类(因为app first策略),然后您的应用程序将尝试将WAR InputSource的实例传递给JDK Unmarshaller,它只接受一个实例JDK InputSource。

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.

有两种解决方案:


  1. 删除所有API jar从您的应用程序,并使用JDK中的那些。例如,删除包含org.xml.sax或org.w3c.dom的jar。

  2. 在WAR中包含引用要引用的类的所有库。例如,在WAR中包含JAXB库的副本。

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

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.

这篇关于WAS 6.1 java.lang.VerifyError:违反了类加载约束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆