Java之谜:需要一个稳定的随机变量,它在JVM中持久存在,但在另一个JVM中不同

Java之谜:需要一个稳定的随机变量,它在JVM中持久存在,但在另一个JVM中不同,java,random,jvm,Java,Random,Jvm,我需要找到一种方法从JVM中获取一个(某种程度上)随机字符串或数字,而不必存储这些字符串或数字。但在JVM的生命周期中,我会多次需要它,因此对该方法的后续调用必须返回相同的值。此外,在JVM重新启动后,相同的代码必须产生不同但仍然稳定的值。随机性的质量并不重要,只要它足够难猜测。只需在不同的虚拟机中以不同的方式播种随机性即可 public class MyClass { private int myStableRandomValue = new Random( System.curre

我需要找到一种方法从JVM中获取一个(某种程度上)随机字符串或数字,而不必存储这些字符串或数字。但在JVM的生命周期中,我会多次需要它,因此对该方法的后续调用必须返回相同的值。此外,在JVM重新启动后,相同的代码必须产生不同但仍然稳定的值。随机性的质量并不重要,只要它足够难猜测。

只需在不同的虚拟机中以不同的方式播种随机性即可

public class MyClass {
     private int myStableRandomValue = new Random( System.currentTimeMillis() ).nextInt();
     ...
}
编辑

如果确实不想存储该值,则可以使用进程ID为上述随机方法种子,并在每次请求该值时调用它——如果潜在攻击者无法访问该进程ID

     private int getMyStableRandomValue() { 
        return new Random( getProcessID() ).nextInt();
     }

只需在不同的虚拟机中以不同的方式播种随机数据

public class MyClass {
     private int myStableRandomValue = new Random( System.currentTimeMillis() ).nextInt();
     ...
}
编辑

如果确实不想存储该值,则可以使用进程ID为上述随机方法种子,并在每次请求该值时调用它——如果潜在攻击者无法访问该进程ID

     private int getMyStableRandomValue() { 
        return new Random( getProcessID() ).nextInt();
     }
研究一下学习的方法。例如,您可以执行以下操作:

RuntimeMXBean rmxb = ManagementFactory.getRuntimeMXBean(); 
String jvmId = rmxb.getVmName() + "-" + rmxb.getStartTime();
// use jvmId.intern().hashCode() as seed for a RNG
正如emroy指出的,两个JVM可能同时启动。如果这是一个问题,我建议将机器的MAC地址连接到
jvmId

InetAddress localHost = InetAddress.getLocalHost();
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
byte[] macAddress = networkInterface.getHardwareAddress();
jvmId += "-" + Arrays.toString(macAddress);
研究一下学习的方法。例如,您可以执行以下操作:

RuntimeMXBean rmxb = ManagementFactory.getRuntimeMXBean(); 
String jvmId = rmxb.getVmName() + "-" + rmxb.getStartTime();
// use jvmId.intern().hashCode() as seed for a RNG
正如emroy指出的,两个JVM可能同时启动。如果这是一个问题,我建议将机器的MAC地址连接到
jvmId

InetAddress localHost = InetAddress.getLocalHost();
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
byte[] macAddress = networkInterface.getHardwareAddress();
jvmId += "-" + Arrays.toString(macAddress);

我建议使用延迟启动的静态对象的哈希代码。下面的代码似乎不起作用。我猜SAXParserFactory实际上并不是懒散地启动的

class One
{
     public static void main ( String [ ] args )
     {
    while(Math.random()<0.99){
        new Object();
    }
    System.out.println(javax.xml.parsers.SAXParserFactory.newInstance().hashCode());
     }
}
第一类
{
公共静态void main(字符串[]args)
{

while(Math.random()我建议使用延迟启动的静态对象的哈希代码。下面的代码似乎不起作用。我猜SAXParserFactory实际上不是延迟启动的

class One
{
     public static void main ( String [ ] args )
     {
    while(Math.random()<0.99){
        new Object();
    }
    System.out.println(javax.xml.parsers.SAXParserFactory.newInstance().hashCode());
     }
}
第一类
{
公共静态void main(字符串[]args)
{


while(Math.random())不能保证在同一个JVM中重复结果。抱歉,尚未完成键入。如果OP想要一个稳定的随机值,上面的代码就足够了。如果OP想要一组可重复的随机值,种子可以存储。@Andy Thomas Cramer-请重新阅读OP的帖子。s/他想要:(1)一个在当前JVM的整个生命周期内相同,但在不同JVM中不同的值;(2)s/他不想存储这样的值。@Louis Wasserman-据我所知,
Math.Random()
不能保证每次使用相同的种子时都能得到相同的结果。@PM77-1。感谢您注意到无存储请求。但是:“如果使用相同的种子创建两个Random实例,并且为每个实例调用相同的方法序列,则它们将生成并返回相同的数字序列。“它不能保证在同一个JVM中重复结果。抱歉,尚未完成键入。如果OP想要一个稳定的随机值,上面的代码就足够了。如果OP想要一组可重复的随机值,种子可以存储。@Andy Thomas Cramer-请重新阅读OP的帖子。s/他想要:(1)一个在当前JVM的整个生命周期内相同,但在不同JVM中不同的值;(2)s/他不想存储这样的值。@Louis Wasserman-据我所知,
Math.Random()
不能保证每次使用相同的种子时都能得到相同的结果。@PM77-1。感谢您注意到无存储请求。但是:“如果使用相同的种子创建两个Random实例,并且为每个实例调用相同的方法序列,则它们将生成并返回相同的数字序列。"如果可以在静态字段中存储一个值,这个问题就会很容易解决。我假设您的意思是,对于每个
java YourClass
调用,这个随机值应该不同。如果可以在静态字段中存储一个值,这个问题就会很容易解决。我假设您的意思是,对于每个
java YourClass
调用,这个随机值应该不同。我相信这个答案满足OP的要求。@PM77-1实际上,如果你看扩展的评论,我认为这个答案不满足要求(我的答案也不满足)。我怀疑没有解决方案。@emroy-你是对的:理论上有可能两个JVM同时启动。我现在意识到,这个问题非常类似于获取一个全局唯一的ID。我将把MAC地址添加到我的解决方案中。@Tilo-这是迄今为止最好的答案。MAC地址没有为我的用例添加任何内容:malicious insider也可以使用它。开始时间毫秒是一个很好的近似值:在JVM的生命周期内持续存在,并且很难猜测。可以从操作系统获得JVM进程的开始时间,但这通常是二次粒度的,所以坏人仍然必须猜测大量的值。@Tilo我实际上非常喜欢这个答案比我的要好,但我认为没有必要同时启动两个JVM。“恶意内幕”“前灯”所担心的是,它可以准确地知道JVM何时启动并将时钟重置为该值。我相信这个答案满足OP的要求。@PM77-1实际上,如果您查看扩展注释,我认为这个答案不满足要求(我的答案也不满足)。我怀疑没有解决方案。@emroy-你是对的:理论上有可能两个JVM同时启动。我现在意识到,这个问题非常类似于获取一个全局唯一的ID。我将把MAC地址添加到我的解决方案中。@Tilo-这是迄今为止最好的答案。MAC地址没有为我的用例添加任何内容:malicious insider也可以使用它。开始时间毫秒是一个很好的近似值:在JVM的生命周期内持续存在,很难猜测。可以获得JVM进程的开始时间f