Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reliability of Random with a constant seed across different versions of Java

Tags:

java

random

In our application, we use Random and SecureRandom to generate some very large sets of information for some clients. After some measurements, we realized that it was faster and less memory-intensive to re-generate the information using seeds stored on disk, than to store and read that information. I looked through the javadoc, and I didn't see anything guaranteeing that, given a constant seed n, the result of, say, new Random(n).nextInt() shall be the same across different versions of Java.

My question is: is this a safe assumption to make for Java 8 and previous versions, that new Random(n).nextInt() in Java 8 shall return the same value than in previous versions of Java?

(For the sake of fairness, I will accept answers answering the above question, even if they don't answer the question below.)

While I know there is no guarantee that this will also be true for later versions of Java, and that this second question shall solicit some opinions, what do you think are the odds that future Java version will change the algorithm used to generate pseudo-random numbers using Random and SecureRandom?

Thanks!

like image 994
Jonathan Pitre Avatar asked Oct 16 '15 13:10

Jonathan Pitre


1 Answers

Yes, this is guaranteed for Random in all versions through Java 8. There don't seem to be any similar guarantees for SecureRandom however.

If you look at the Javadocs for Random, you can see this:

If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers. In order to guarantee this property, particular algorithms are specified for the class Random. Java implementations must use all the algorithms shown here for the class Random, for the sake of absolute portability of Java code. However, subclasses of class Random are permitted to use other algorithms, so long as they adhere to the general contracts for all the methods.

Emphasis mine. So some thought was clearly given to this concern, and the decision was to specify the underlying algorithms in the documentation for the class. People could theoretically provide a differing implementation, but then it wouldn't be in compliance with the Java specification.

For further evidence, look at what that implementation is between versions. For example, the next method is defined the exact same way in every version since at least Java 1.4 (as far back as I looked).

seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
return (int)(seed >>> (48 - bits));

Since this is the same, you have a clear guarantee that, not only will the values returned be the same across versions, but you can reliably calculate the same values yourself using this algorithm.

However, I can't find any similar guarantees for SecureRandom, and since Random says that subclasses are free to break this rule, then it's not guaranteed that it will be consistent between versions. The only evidence I can find for this though is a forum post of someone observing inconsistent values being generated with it. According to Ian McLaird's answer, SecureRandom does seem to be generating consistent values in practice, so you might decide it's worth the risk to assume it will work. However, this behavior does not seem to be guaranteed.

To answer the second part of your question, it's theoretically possible that they could change it. However, since it is currently a well-defined operation, and given how hard Oracle works to avoid breaking backwards compatibility, I'd consider it incredibly unlikely.

like image 102
resueman Avatar answered Oct 12 '22 21:10

resueman