7

同じ Tomcat で実行されている 2 つの別々の戦争で Amazon S3 SDK を使用しています。Spring サービスの 1 つの @PostConstruct で AmazonS3Client を初期化します。

これらの戦争を別々に実行すると、通常はすべて正常に動作します。それらを一緒に実行すると、そのうちの 1 つ (2 番目に起動するもの) が次の例外をスローします。

com.amazonaws.AmazonClientException: XMLReader の sax ドライバーを初期化できませんでした

これが発生した場合、AmazonClientException をキャッチした後、次のシステム プロパティを設定する回避策があります。

try {
  init();
} catch (AmazonClientException ase) {
  System.setProperty("org.xml.sax.driver", "com.sun.org.apache.xerces.internal.parsers.SAXParser");
  init();
}

しかし、これはもちろん恐ろしいことです。これを行うより良い方法はありますか?これらの状況でなぜこれが発生するのですか?

更新: 最初は、AmazonS3Client の初期化を @PostConstruct から移動し、遅延して初期化すると、このエラーが完全に防止されたように見えました。しかし、どうやらそれは時々発生するようです - 私が両方ではなく一方の戦争だけを実行したとしても。

4

2 に答える 2

5

XMLReader は一連の手順を実行して、使用するドライブを識別します。ドキュメントの引用

  • システム プロパティ org.xml.sax.driver に値がある場合、それは XMLReader クラス名として使用されます。
  • JAR「サービス API」は、ランタイムで使用可能な jar ファイル内の META-INF/services/org.xml.sax.driver ファイルでクラス名を検索するために使用されます。
  • SAX パーサーの配布では、(このリストの) 前のオプションが成功しなかった場合にのみ有効になるデフォルトの XMLReader クラス名を提供することが強く推奨されます。
  • 最後に、ParserFactory.makeParser() がシステムのデフォルト SAX1 パーサーを返すことができる場合、そのパーサーは ParserAdapter にラップされます。(これは、org.xml.sax.parser システム プロパティが頻繁に使用される SAX1 環境の移行支援です。)

AWS SDKのコードを見ると...

public XmlResponsesSaxParser() throws AmazonClientException {
    // Ensure we can load the XML Reader.
    try {
        xr = XMLReaderFactory.createXMLReader();
    } catch (SAXException e) {
        // oops, lets try doing this (needed in 1.4)
        System.setProperty("org.xml.sax.driver", "org.apache.crimson.parser.XMLReaderImpl");
        try {
            // Try once more...
            xr = XMLReaderFactory.createXMLReader();
        } catch (SAXException e2) {
            throw new AmazonClientException("Couldn't initialize a sax driver for the XMLReader");
        }
    }
}

そのコードについて気に入らない点がいくつかあります。

  1. SaxException e の根本原因は食い尽くされています。
  2. SaxException e2 の根本原因も食い尽くされています。コードが最低限行うべきことは、根本原因を示す警告を出力することです。
  3. レベル フレームワーク コード内で System.setProperty() を使用すると、デバッグが困難な問題が発生する可能性があります。

これらの点により、問題のデバッグが難しくなります。私ができる最善の知識に基づいた推測は、クリムゾン パーサーは 1 つのクラス ローディング パスではアクセスできるが、もう 1 つのクラス ローディング パスではアクセスできないということです。問題を特定する決定的な方法は、コードにブレークポイントを設定してリーダーをインスタンス化し、根本的な原因を特定することです。

于 2012-10-21T12:24:44.893 に答える
1

シングルトン モデルを使用しているため、この呼び出しを分離する唯一の方法は、SAX 関連の JAR のセット全体を WAR 自体に含めることです (それらは異なるクラスローダーにロードされます)。私が同じ問題を抱えていたとき、それは私にとってはうまくいきました。これは PermGen に影響を与えますが、どうすればよいでしょうか。または、S3 ライブラリを変更しても構わない場合は、このメソッドを静的に同期し、ライブラリを共有してください。Amazonの人たちがこの呼び出しを同期させれば、これは問題になりません.

于 2012-10-28T09:22:28.737 に答える