如何在第三方类中为java.util.Random提供特定的种子?
我有一个Java程序,可加载第三方类文件(我未编写的类)并执行它们。这些类通常使用java.util.Random
,默认情况下,每次实例化时都会生成随机的起始种子值。出于可复制性的原因,我希望每次给这些类相同的起始种子,仅在我自己决定的情况下才对其进行更改。
以下是一些显而易见的解决方案,以及为什么它们不起作用:
- 在第三方类文件中使用其他随机类。这里的问题是我只加载类文件,而不能修改源文件。
- 使用自定义类加载器加载我们自己的Random类,而不是JVM的版本。这种方法行不通,因为Java不允许类加载器覆盖
java
包中的类。 - 为我们自己交换rt.jar的
java.util.Random
实现,或者将文件放入JVM的受信任位置。这些方法要求应用程序的用户将他们的JVM安装在其机器上,这是不好的。 - 在引导类路径中添加一个自定义的java.util.Random类。尽管从技术上讲这是可行的,但对于此特定应用程序而言,这是不切实际的,因为该应用程序旨在供最终用户从IDE运行。我想让用户方便地运行该应用程序,这意味着强迫他们设置其bootclasspath是一件很痛苦的事情。我无法将其隐藏在脚本中,因为它旨在从像Eclipse这样的IDE中运行(以便于调试)。
那我该怎么做呢?
解决方案
我们可以使用AOP截获对Random的调用,并将arg旋转到所需的位置。
山姆
"使用定制的类加载器来加载我们自己的Random类而不是JVM的版本。这种方法将行不通,因为Java不允许类加载器覆盖Java包中的类。"
如何更改bootclasspath以使用自定义Random类?
BR
〜A
尽管我们可能不会为" java.x"和" sun.x"包简单地更改类加载器,但是有一种方法可以估算这些类的类加载(并安装"在对字节进行字节编码并加载后"侦听器),因此我们从这些包中加载类后,可以设置类似种子的内容。提示:使用反射。
无论如何,只要我没有进一步的信息就可以确切地实现我们想要的目标,就很难在这里为我们提供帮助。
P.S .:请注意," static {}"块可能会再次妨碍我们处理种子。
选项2实际上可以按照以下说明工作。
我们将需要(如anjab所述)更改引导程序类路径。
在程序的命令行中,我们需要添加以下内容:
java -Xbootclasspath / p:C:\ your \ random_impl.jar YourProgram
假设我们使用的是Windown机器或者任何操作系统中的问题的路径。
该选项在加载rt.jar之前将类添加到jar文件中。因此,Random将在rt.jar Random类之前加载。
通过键入以下内容来显示用法:
java -X
它显示JVM具有的所有X(tra)功能。它可能不可用
在其他虚拟机实现(例如JRockit或者其他)上,但它在Sun JVM上。
-Xbootclasspath / p:放在引导类路径的前面
我在应将默认ORB类替换为其他ORB实现的应用程序中使用了这种方法。 ORB类是Java Core的一部分,从来没有任何问题。
祝你好运。
考虑修改第三方库,以使它们对它们的Random实例使用seed。尽管我们没有源代码,但是我们可能可以编辑字节码来执行此操作。为此,一种有用的工具包是ASM。
是的,选项2在起作用:
为了测试目的,创建了两个类,名为ThirdPartyClass.java
和Random.java
。
从ThirdPartyClass.class
创建了jar
jar -cvf tpc.jar ThirdPartyClass.class
从Random.class
创建了jar
jar -cvf rt123.jar Random.class
之后,执行以下命令:
java -Xbootclasspath/p:tcp.jar:rt123.jar -cp . -verbose ThirdPartyClass
输出将是:" 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)