10

環境は Linux 上の WAS 6.1 で、xercesImpl.jar のクラスを使用する Web アプリケーションをデプロイします。

会社のポリシーの制限により、アプリは次の設定で展開する必要があります。

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

これまでの分析

WAS は org.apache.xerces.jaxp.DocumentBuilderImpl の実装を提供しているようです。これは、WAR ファイルから xercesImpl.jar を削除しても同じエラー (ClassNotFoundException ではない) が発生する可能性があるためです。したがって、WAS は、コンパイル済みのクラス ファイル内の参照と互換性のない独自のコピーを使用して参照を解決しているようです。ただし、私が見つけることができる「xercesImpl.jar」の唯一の他のインスタンス (アプリでデプロイされたコピーを除く) は deploytool、アプリ サーバーの外部にあるように見える directory にあります。

WASのすべてのjarファイル(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 のバージョンが使用されると予想されます。これは、私たちが実際に見ているものとは逆のように見えます。

質問:

クラスローダ委任設定は、上記の情報とどのように相互作用して、観察された動作をもたらしていますか?

4

6 に答える 6

14

WAR には org.xml.sax または org.w3c.dom クラスも含まれており、これらのクラスも参照するアプリケーションの外部にあるクラスを参照しています。これにより、アプリケーション クラス ローダーが同じクラスの 2 つのインスタンスを認識できるシナリオが設定されます。これはリンケージ エラーです。

たとえば、アプリケーションが javax.xml.bind.Unmarshaller.unmarshal(InputSource) を使用する場合、Unmarshaller は JDK からロードされ、Unmarshaller クラスは JDK InputSource に対してのみ可視性を持ちます。アプリケーションがその InputSource を作成するとき、WAR からクラスをロードし (「アプリ ファースト」ポリシーのため)、アプリケーションは WAR InputSource のインスタンスを JDK Unmarshaller に渡そうとします。 JDK 入力ソース。

次の 2 つの解決策があります。

  1. アプリケーションからすべての API jar を削除し、JDK のものを使用します。たとえば、org.xml.sax または org.w3c.dom を含む jar を削除します。
  2. 参照するクラスを参照するすべてのライブラリを WAR に含めます。たとえば、JAXB ライブラリのコピーを WAR に含めます。

私の経験では、JVM はリンケージが追加される原因についてお粗末な情報を提供するため、リンケージ エラーを追跡するのは非常に困難です。私は通常、クラスローダーのトレースを有効にして問題を再現し、アプリケーションの外部からロードされたクラスが、アプリケーション内に存在することがわかっているクラスを参照しているように見えるまで、逆方向に歩きます。

于 2010-05-19T00:00:25.243 に答える
0

私たちの問題は、WAS 8.5 への展開でした。

この Web アプリケーションには、cxf によって生成された Web サービス クライアントがあります。問題ない。

MIME タイプの検出のために tika-parser を追加すると、この問題が発生しました。

3 つの依存関係を除外しました。

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

それらが除外されると、アプリケーションは正常に開始されました。

于 2014-09-24T02:35:47.563 に答える
-1

バイトコード検証を無効にする

java.lang.VerifyError -クラス ファイルが Websphere JVM にロードされると、ランタイム未チェック例外が発生し、次のプロセスでバイト コードの検証が行われます。バイト コードの検証中に、クラスが JVM の制約に違反している場合、このエラーが表示されます。

バイトコード検証を無効にします。に行く

管理コンソール->server1 ->Java およびプロセス管理->process definition->JVM 引数`

そして、JVM 引数で次の文字列を渡します

 -Xverify:none 

ワークスペースで ApplicationDeploymentDescriptor xml ファイルを開き、配置タブに移動し、戦争の PARENT_LAST と最初のオプションを選択します。これにより、xml 検証エラーが停止します。

于 2015-04-11T11:18:50.580 に答える
-2

「親クラスローダーを最初に」に変更すると、例外は表示されません。これは、予想される動作に反します。

はい、そのとおりです。そのような動作を確認できる唯一の方法です。「本当にクラス・ローダーを入手できますか?」をご覧になることをお勧めします。あなたの質問に対する単一または短い答えはないので、話してください。

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

于 2010-05-19T07:30:55.560 に答える