サードパーティのクラスで java.util.Random に特定のシードを与えるにはどうすればよいですか?
-
01-07-2019 - |
質問
サードパーティのクラス ファイル (私が作成したものではないクラス) をロードして実行する Java プログラムがあります。これらのクラスはよく使用します java.util.Random
, デフォルトでは、インスタンス化されるたびにランダムな開始シード値が生成されます。再現性の理由から、これらのクラスには毎回同じ開始シードを与え、私の裁量でのみ変更したいと考えています。
以下に、明らかな解決策のいくつかと、それらが機能しない理由を示します。
サードパーティのクラスファイルで別の Random クラスを使用します。ここでの問題は、クラスファイルをロードするだけで、ソースを変更できないことです。
カスタム クラスローダーを使用して、JVM のバージョンの代わりに独自の Random クラスをロードします。Java ではクラスローダーがクラスをオーバーライドすることを許可していないため、このアプローチは機能しません。
java
パッケージ。rt.jar を交換します
java.util.Random
独自の実装を行うか、JVM の信頼できる場所にファイルを置きます。これらのアプローチでは、アプリケーションのユーザーがマシン上の JVM インストールをいじる必要があり、役に立ちません。カスタムの追加
java.util.Random
クラスをブートクラスパスに追加します。これは技術的には機能しますが、この特定のアプリケーションでは、エンド ユーザーが IDE から実行することを目的としているため、現実的ではありません。ユーザーにとってアプリの実行を便利にしたいと考えています。つまり、ユーザーにブートクラスパスの設定を強制するのは面倒です。これは Eclipse などの IDE から実行することを目的としているため (デバッグを容易にするため)、スクリプト内でこれを隠すことはできません。
では、どうすればよいでしょうか?
解決
サードパーティのライブラリを変更して、Random インスタンスに Seen を使用するようにすることを検討してください。ソース コードはありませんが、バイトコードを編集して実行できる可能性があります。そのようなことを行うための便利なツールキットの 1 つは、 ASM.
他のヒント
オプション 2 は、次の手順で実際に機能します。
(anjab が言ったように) ブートストラップ クラス パスを変更する必要があります。
プログラムのコマンドラインに以下を追加する必要があります。
java -Xbootclasspath/p:C:\your andom_impl.jar あなたのプログラム
Windown マシンまたは任意の OS のパスを使用していると仮定します。
このオプションは、rt.jar がロードされる前に、jar ファイルにクラスを追加します。したがって、Random は rt.jar Random クラスがロードされる前にロードされます。
次のように入力すると、使用法が表示されます。
java -X
JVM が持つすべての X(tra) 機能が表示されます。Jrockitなどの他のVM実装では利用できない場合がありますが、Sun JVMにはあります。
-Xbootクラスパス/p:ブートストラップクラスパスの前に追加します
私は、デフォルトの ORB クラスを他の ORB 実装に置き換える必要があるアプリケーションでこのアプローチを使用しました。ORB クラスは Java コアの一部であり、何の問題もありませんでした。
幸運を。
AOP を使用して Random への呼び出しをインターセプトし、引数を必要なものに変更することができます。
サム
「java.x」および「sun.x」パッケージのクラスローダーを簡単に変更することはできませんが、これらのクラスのクラスロードを計算する(そして「クラスがバイトコード化されてロードされた後」リスナーをインストールする)方法はあります。これらのパッケージからクラスをロードした後にシードのようなものを設定できます。ヒント:反射を使用します。
とにかく、あなたが具体的に何を達成したいのかについてのさらなる情報がない限り、ここであなたを助けるのは非常に困難です。
追記:「静的 {}」ブロックは、シードをいじるのを妨げる可能性があることに注意してください。
「カスタム クラスローダーを使用して、JVM のバージョンではなく独自の Random クラスをロードします。Java ではクラスローダーが Java パッケージ内のクラスをオーバーライドすることを許可していないため、このアプローチは機能しません。」
カスタム Random クラスを使用するようにブートクラスパスを変更してみてはいかがでしょうか?
BR、〜a
はい、オプション 2 は機能しています。という名前のテスト目的で 2 つのクラスを作成しました ThirdPartyClass.java
そして Random.java
からjarを作成しました ThirdPartyClass.class
jar -cvf tpc.jar ThirdPartyClass.class
からjarを作成しました Random.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;
}
}
Mahaveer Prasad Maliに感謝します