3

ここで難問に直面しています。

私が開発したアプリケーションの 1 つは、JAXPのDocumentBuilderFactoryクラスの正しくない実装をロードしています。この動作は、別のチーム/会社によって構築された別のアプリケーションの別のクラスが原因であると後で推測されました。上記のクラスは、以下のような静的ブロックを含めることにより、ロード時に優先 DocumentBuilderFactory クラスを変更しました。

  static
  {
    System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "a new factory");
  }

DocumentBuilderFactory.newInstanceメソッドの Javadoc を見れば、newInstance メソッドが呼び出されたときに、上記のコードがすべてのアプリケーションに返されるパーサーの実装を変更していたことは明らかです。

この問題を修正するパッチが適用されましたが、この質問をするようになりました-どのクラスが実行時に System.setProperty 呼び出しを実行しているかをどのように判断しますか?

サーバーにデプロイされたすべてのアプリケーションのすべてのソースにアクセスできなかったという非常に単純な理由で、犯人を釘付けにする変更された System クラスを使用して、OpenJDK のカスタム ビルドを作成しました。しかし、これが可能になったのは、本番環境が完全に複製されたからです。したがって、質問は次のように解釈することもでき ます。実稼働環境で、実行時に System.setProperty 呼び出しを実行しているクラスをどのように判断するのですか?

4

5 に答える 5

6

System.setPropertyは、インストールされている場合、 SecurityManagerによってチェックされます。

独自の MySecurityManager を作成し、実行時にデプロイできます。checkPropertyAccessメソッドが呼び出されると、独自の SecurityManager が現在のスタックトレースなどの情報をログに記録できます。

public class MySecurityManager extends SecurityManager
{

    public MySecurityManager()
    {
        super();
    }

    @Override
    public void checkPropertyAccess(String key)
    {
        if ("javax.xml.parsers.DocumentBuilderFactory".equals(key))
        {
            System.err.println("checkPropertyAccess(String :" + key + "): ");
            Thread.currentThread().dumpStack(); // or anything useful for
                                                // logging the context.
            new Throwable().printStackTrace(); // whatever, or use it with
            // PrintStream/PrintWriter, or some logging framework if configured.
        }
        super.checkPropertyAccess(key);
    }

    @Override
    public void checkPermission(Permission perm)
    {
        if (perm instanceof PropertyPermission)
        {
            PropertyPermission propPerm = (PropertyPermission) perm;
            System.err.println("checkPropertyAccess(String:" + propPerm.getName() + "):");
            Thread.currentThread().dumpStack(); // or anything useful for
                                                // logging the context.
            new Throwable().printStackTrace(); // whatever, or use it with
            // PrintStream/PrintWriter, or some logging framework if configured.
        }
        super.checkPermission(perm);
    }
}
于 2010-11-17T19:09:37.407 に答える
2

文字列リテラルはクラス ファイル形式で UTF8 エンコードされており、問題のある呼び出し元がコードを使用してプロパティ名を連結していると想定する理由がないため、クラスパスからすべての JAR を 1 つのディレクトリに展開し、再帰的な grep を試してみました。クラスファイルを介して「javax.xml.parsers.DocumentBuilderFactory」用。少なくとも、この文字列をリテラルとして含むすべてのクラス ファイルが見つかり、多くの誤検知が発生しないことを願っています。

間違った実装のクラス名がより簡単に識別できる場合は、代わりにそれを検索する方が賢いかもしれません。

于 2010-11-17T17:34:00.567 に答える
1

私は2つの解決策を知っています

  1. アスペクト フレームワーク (aspectJ など) を使用する
  2. System クラスを変更 (setProperty() メソッドにロギングを追加) するとnew Throwable().printStacktrace(); 、メソッドが呼び出された場所が報告されます。

オプションを指定してアプリケーションを実行し-Xbootclasspath/p、バージョンの System クラスを配置します。

-Xbootclasspath/p:<directories and zip/jar files separated by ;> ブートストラップ クラスパスの前に追加

非常に単純なので、2 番目の解決策を好みます。

于 2010-11-17T17:13:50.747 に答える
1

アプリケーションをデバッグ モードで起動し、Eclipse で接続し、ブレークポイントを設定して、呼び出し階層でどのクラスが実行されているかを確認しますhttp://www.eclipsezone.com/eclipse/forums/t53459.html

于 2010-11-17T16:22:34.887 に答える
0

アスペクトフレームワークのユース ケースのようですね。

于 2010-11-17T16:21:55.853 に答える