5

サードパーティのクラス ファイル (私が書いていないクラス) をロードして実行する Java プログラムがあります。これらのクラスはjava.util.Random、デフォルトで、インスタンス化されるたびにランダムな開始シード値を生成する を使用することがよくあります。再現性の理由から、これらのクラスには毎回同じ開始シードを与え、私の裁量でのみ変更したいと考えています。

明らかな解決策のいくつかと、それらが機能しない理由を次に示します。

  1. サードパーティのクラスファイルで別のランダム クラスを使用します。ここでの問題は、クラス ファイルをロードするだけで、ソースを変更できないことです。

  2. カスタム クラスローダーを使用して、JVM のバージョンの代わりに独自の Random クラスをロードします。javaJava ではクラスローダーがパッケージ内のクラスをオーバーライドできないため、このアプローチは機能しません。

  3. rt.jar のjava.util.Random実装を独自のものに交換するか、ファイルを JVM の信頼できる場所に置きます。これらのアプローチでは、アプリケーションのユーザーが自分のマシンにインストールされている JVM をいじる必要があり、役に立ちません。

  4. bootclasspath にカスタムjava.util.Randomクラスを追加します。これは技術的には機能しますが、この特定のアプリケーションでは、このアプリケーションはエンド ユーザーが IDE から実行することを目的としているため、実用的ではありません。アプリをユーザーにとって便利に実行できるようにしたいので、ブートクラスパスを強制的に設定するのは面倒です。これは、Eclipse などの IDE から実行することを目的としているため (デバッグを容易にするため)、スクリプトで非表示にすることはできません。

では、どうすればこれを行うことができますか?

4

6 に答える 6

3

オプション 2 は、次の手順で実際に機能します。

(anjab が言ったように) ブートストラップ クラス パスを変更する必要があります。

プログラムのコマンドラインで、次を追加する必要があります。

java -Xbootclasspath/p:C:\your\random_impl.jar あなたのプログラム

Windown マシンを使用しているか、任意の OS でそのパスを使用していると仮定します。

このオプションは、rt.jar がロードされる前にクラスを jar ファイルに追加します。したがって、 rt.jar Random クラスがロードされる前に Random がロードされます。

使用法は、次のように入力して表示されます。

java -X

JVM が持つすべての X(tra) 機能が表示されます。JRockit などの他の VM 実装では使用できない場合がありますが、Sun JVM では使用できます。

-Xbootclasspath/p: ブートストラップ クラス パスの先頭に追加

デフォルトの ORB クラスを他の ORB 実装に置き換える必要があるアプリケーションで、このアプローチを使用しました。ORB クラスは Java コアの一部であり、問​​題はありませんでした。

幸運を。

于 2008-09-20T01:20:25.980 に答える
2

サード パーティのライブラリを変更して、それらの Random インスタンスに see を使用することを検討してください。ソースコードはありませんが、おそらくバイトコードを編集してそれを行うことができます。これを行うための便利なツールキットの 1 つがASMです。

于 2008-09-20T03:56:21.737 に答える
1

AOP を使用して Random の呼び出しをインターセプトし、引数を必要なものに調整できます。

サム

于 2008-09-20T01:00:55.120 に答える
1

「java.x」および「sun.x」パッケージのクラスローダーを簡単に変更することはできませんが、これらのクラスのクラスのロードを計算する (および「クラスがバイトコード化されてロードされた後に」リスナーをインストールする) 方法があります。これらのパッケージからクラスをロードした後、シードのようなものを設定できます。ヒント: リフレクションを使用します。

とにかく、あなたが何を達成したいのか、それ以上の情報がない限り、ここであなたを助けることはかなり難しいです.

PS: 「静的 {}」に注意してください。ブロックは、シードをいじるのを妨げる可能性があります。

于 2008-09-20T01:11:28.823 に答える
0

はい、オプション2が機能しています。テスト目的で2つのクラスを作成しましたThirdPartyClass.javaRandom.java

から作成されたjarThirdPartyClass.class

jar -cvf tpc.jar ThirdPartyClass.class

から作成されたjarRandom.class

jar -cvf rt123.jar Random.class

その後、次のコマンドで実行します。

java  -Xbootclasspath/p:tcp.jar:rt123.jar -cp . -verbose ThirdPartyClass

出力は次のようになります。seed value for ThirdPartyClass-> 1

ソースコードThirdPartyClass.java----->

import java.util.Random;

public class ThirdPartyClass {
    ThirdPartyClass(long seed ) {
        System.out.println("seed value for ThirdPartyClass-> "+seed);
    }   

    public static void main(String [] args) {
        ThirdPartyClass tpc=new ThirdPartyClass(new Random().nextLong());
    }
}

ソースコードRandom.java------->

package java.util;

import java.io.Serializable;

public class Random extends Object implements Serializable
{
    public Random() {
    }

    public Random(long seed) {
    }

    public long nextLong() {
        return 1;
    }
}

ありがとうMahaveerPrasadMali

于 2010-06-04T07:45:22.767 に答える
0

「カスタム クラスローダーを使用して、JVM のバージョンの代わりに独自の Random クラスをロードします。Java では、クラスローダーが Java パッケージ内のクラスをオーバーライドすることを許可していないため、このアプローチは機能しません。」

カスタム Random クラスを使用するように bootclasspath を変更するのはどうですか?

BR、~A

于 2008-09-20T01:01:46.587 に答える