Frage

Ich habe ein Java-Programm, das von Drittanbietern Klassendateien (Klassen I nicht schreiben) lädt und führt sie aus. Diese Klassen verwenden oft java.util.Random, die standardmäßig generiert zufällige Startstartwerte jedes Mal instanziiert wird. Aus Gründen der Reproduzierbarkeit, möchte ich jedes Mal, wenn diese Klassen den gleichen Ausgangs Samen geben, ist es nur in meinem Ermessen zu ändern.

Hier sind einige der offensichtlichen Lösungen, und warum sie nicht funktionieren:

  1. Verwenden Sie eine andere Zufallsklasse in den Klassendateien von Drittanbietern. Das Problem hier ist, ich nur die Klassendateien laden, und die Quelle nicht ändern kann.

  2. einen benutzerdefinierten Classloader verwendet unsere eigene Klasse Random statt der JVM-Version zu laden. Dieser Ansatz wird nicht funktionieren, weil Java nicht Classloader erlaubt Klassen im java Paket außer Kraft zu setzen.

  3. auslagern des java.util.Random Implementierung des rt.jar für unsere eigenen, oder Dateien in vertrauenswürdigen Speicherort für die JVM setzen. Diese Ansätze erfordern die Benutzer der Anwendung mit der JVM Unordnung auf ihrem Computer installiert haben, und sind nicht gut.

  4. eine benutzerdefinierte java.util.Random Klasse zum bootclasspath Hinzufügen. Während dies wäre es technisch funktioniert, für diese spezielle Anwendung, ist unpraktisch, da diese Anmeldung soll für Benutzer Ende von einer IDE auszuführen. Ich möchte die App für die Benutzer bequemer machen, laufen, was bedeutet, sie zwingt, ihre bootclasspath zu setzen ist ein Schmerz. Ich kann dies nicht darüber hinwegtäuschen, in einem Skript, da es beabsichtigt ist von einem IDE wie Eclipse ausgeführt werden (für eine einfache Fehlersuche.)

Wie kann ich das tun?

War es hilfreich?

Lösung

Beachten Sie die Bibliotheken von Drittanbietern modifiziert haben sie eine für ihre Zufalls Fälle gesehen, verwenden. Obwohl Sie nicht den Quellcode haben, können Sie wahrscheinlich den Bytecode bearbeiten, es zu tun. Ein hilfreicher Toolkit für diese tun, ist ASM .

Andere Tipps

Ihre Option 2 auch tatsächlich funktioniert, mit den folgenden Richtungen.

Sie müssen (wie anjab sagte), um den Bootstrap-Klassenpfad zu ändern.

In der Befehlszeile des Programms Sie Folgendes hinzufügen müssen:

java -Xbootclasspath / p: C: \ Ihr \ random_impl.jar YourProgram

Angenommen, Sie sind auf Windown Maschine oder den Weg für diese Angelegenheit in jedem Betriebssystem.

Diese Option fügt die Klassen in JAR-Dateien, bevor die rt.jar geladen werden. So wird Ihr Zufall geladen werden, bevor die rt.jar Zufall Klasse des Fall ist.

Die Nutzung durch Eingabe angezeigt wird:

java -X

Es zeigt alle X (tra) verfügt de JVM hat. Es kann durch nicht verfügbar  auf anderen VM-Implementierungen wie JRockit oder andere, aber es ist es auf Sun JVM.

-Xbootclasspath / p: prepend vor Bootstrap-Classpath

Ich habe diesen Ansatz in einer Anwendung verwenden, bei denen die Standard-ORB-Klasse sollte mit anderen ORB Implementierung ersetzt werden. ORB-Klasse ist Teil des Java Core und hatte nie ein Problem.

Viel Glück.

Sie könnten AOP verwenden, um die Anrufe zu Zufall abzufangen und die ARG twiddle, was Sie wollen.

Sam

Auch wenn Sie nicht den Klassenlader triviale für „java.x“ ändern und „sun.x“ -Pakete, ist es eine Möglichkeit, das Laden von Klassen zu rechnen (und installiere ein „nach wurde Klasse bytecoded und geladen“ Hörer) von Thesen Klassen , so könnten Sie so etwas wie die Samen nach dem Laden der Klassen aus diesen Paketen eingestellt. . Hinweis: Verwenden Reflexion

Wie auch immer, solange ich nicht weitere Informationen haben, was genau Sie erreichen wollen, ist es ziemlich schwer, Sie hier zu helfen.

P. S .: Beachten Sie, dass "static {}." - Blöcke behindern können Sie rund um mit Samen durcheinander, wieder

„eine benutzerdefinierte Classloader verwenden unsere eigene Klasse Random statt der JVM-Version zu laden. Dieser Ansatz wird nicht funktionieren, weil Java Classloader nicht zulässt, dass Klassen in der Java-Paket außer Kraft zu setzen.“

Wie über die bootclasspath Änderung Ihrer benutzerdefinierten Klasse Random zu benutzen?

BR, ~ A

Ja Option 2 arbeiten: erstellt zwei Klassen zu Testzwecken genannt ThirdPartyClass.java und Random.java

erstellt jar von ThirdPartyClass.class

jar -cvf tpc.jar ThirdPartyClass.class

erstellt jar von Random.class

jar -cvf rt123.jar Random.class

danach ausführen mit folgendem Befehl ein:

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

Der Ausgang wird sein: seed value for ThirdPartyClass-> 1

Quellcode 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());
    }
}

Quellcode 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;
    }
}

Danke Mahaveer Prasad Mali

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top