5

我有一个 Java 程序,它加载第三方类文件(我没有编写的类)并执行它们。这些类经常使用java.util.Random,默认情况下,每次实例化时都会生成随机的起始种子值。出于可重复性的原因,我想每次都为这些类提供相同的起始种子,仅由我自行决定更改它。

以下是一些明显的解决方案,以及为什么它们不起作用:

  1. 在第三方类文件中使用不同的 Random 类。这里的问题是我只加载类文件,不能修改源。

  2. 使用自定义类加载器来加载我们自己的 Random 类,而不是 JVM 的版本。这种方法不起作用,因为 Java 不允许类加载器覆盖java包中的类。

  3. 将 rt.jar 的java.util.Random实现替换为我们自己的,或者将文件放入 JVM 的受信任位置。这些方法要求应用程序的用户在他们的机器上安装 JVM,这并不好。

  4. 将自定义java.util.Random类添加到引导类路径。虽然这在技术上可行,但对于这个特定的应用程序来说,这是不切实际的,因为这个应用程序是供最终用户从 IDE 运行的。我想让用户方便地运行应用程序,这意味着强迫他们设置引导类路径是一件痛苦的事情。我无法将其隐藏在脚本中,因为它旨在从 Eclipse 之类的 IDE 中运行(以便于调试。)

那么我该怎么做呢?

4

6 回答 6

3

您的选项 2 将按照以下说明实际工作。

您将需要(如 anjab 所说)更改引导类路径。

在程序的命令行中,您需要添加以下内容:

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

假设您使用的是 Windown 机器或任何操作系统中的相关路径。

该选项在加载 rt.jar 之前将类添加到 jar 文件中。因此,您的 Random 将在 rt.jar Random 类之前加载。

通过键入以下内容显示用法:

java -X

它显示了 JVM 具有的所有 X(tra) 功能。它可能在其他 VM 实现(例如 JRockit 或其他)上不可用,但它在 Sun JVM 上存在。

-Xbootclasspath/p:在引导类路径前面添加

我在一个应用程序中使用了这种方法,其中默认的 ORB 类应该替换为其他 ORB 实现。ORB 类是 Java 核心的一部分,从来没有任何问题。

祝你好运。

于 2008-09-20T01:20:25.980 回答
2

考虑修改第三方库,让他们为他们的 Random 实例使用 seen。尽管您没有源代码,但您可以编辑字节码来完成它。一个有用的工具包是ASM

于 2008-09-20T03:56:21.737 回答
1

您可以使用 AOP 拦截对 Random 的调用并将 arg 调整为您想要的。

山姆

于 2008-09-20T01:00:55.120 回答
1

尽管您可能不会轻易更改“java.x”和“sun.x”包的类加载器,但有一种方法可以计算这些类的类加载(并安装“在类被字节编码和加载后”侦听器),所以你从这些包中加载类后,可以设置类似种子的东西。提示:使用反射。

无论如何,只要我没有进一步的信息,你究竟想要达到什么目标,在这里很难帮助你。

PS:请注意,“静态{}” - 块可能会再次阻碍您弄乱种子。

于 2008-09-20T01:11:28.823 回答
0

“使用自定义类加载器来加载我们自己的 Random 类而不是 JVM 的版本。这种方法将不起作用,因为 Java 不允许类加载器覆盖 java 包中的类。”

如何更改引导类路径以使用您的自定义 Random 类?

BR,~A

于 2008-09-20T01:01:46.587 回答
0

是的,选项 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;
    }
}

谢谢马哈维尔·普拉萨德·马里

于 2010-06-04T07:45:22.767 回答