Skip to content

Commit 67e2bf6

Browse files
committed
Add a unique number to be XORed with the thread-local random sequence
The JVM unique number tries to mitigate the fact that the thread local random is not seeded with a secure random seed by default. Their seeds are based on temporal data and predefined constants. Although the seeds are unique per JVM, they are not across JVMs. It helps to generate different sequences of numbers even if two ThreadLocalRandom are by chance instantiated with the same seed. Of course it doesn't better the output, but doesn't hurt either.
1 parent 78b99bf commit 67e2bf6

File tree

1 file changed

+32
-8
lines changed
  • src/main/java/com/github/f4b6a3/uuid/alt

1 file changed

+32
-8
lines changed

src/main/java/com/github/f4b6a3/uuid/alt/GUID.java

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.nio.charset.StandardCharsets;
3030
import java.security.MessageDigest;
3131
import java.security.NoSuchAlgorithmException;
32+
import java.security.SecureRandom;
3233
import java.time.Instant;
3334
import java.util.Arrays;
3435
import java.util.Objects;
@@ -208,9 +209,12 @@ public GUID(String string) {
208209
* @return a GUID
209210
*/
210211
public static GUID v1() {
212+
211213
final long time = gregorian();
214+
212215
final long msb = (time << 32) | ((time >>> 16) & (MASK_16 << 16)) | ((time >>> 48) & MASK_12);
213-
final long lsb = ThreadLocalRandom.current().nextLong() | MULTICAST;
216+
final long lsb = LazyHolder.random() | MULTICAST;
217+
214218
return version(msb, lsb, 1);
215219
}
216220

@@ -270,9 +274,8 @@ public static GUID v3(GUID namespace, String name) {
270274
* @return a GUID
271275
*/
272276
public static GUID v4() {
273-
ThreadLocalRandom random = ThreadLocalRandom.current();
274-
final long msb = random.nextLong();
275-
final long lsb = random.nextLong();
277+
final long msb = LazyHolder.random();
278+
final long lsb = LazyHolder.random();
276279
return version(msb, lsb, 4);
277280
}
278281

@@ -309,9 +312,12 @@ public static GUID v5(GUID namespace, String name) {
309312
* @return a GUID
310313
*/
311314
public static GUID v6() {
315+
312316
final long time = gregorian();
317+
313318
final long msb = ((time & ~MASK_12) << 4) | (time & MASK_12);
314-
final long lsb = ThreadLocalRandom.current().nextLong() | MULTICAST;
319+
final long lsb = LazyHolder.random() | MULTICAST;
320+
315321
return version(msb, lsb, 6);
316322
}
317323

@@ -327,10 +333,12 @@ public static GUID v6() {
327333
* @return a GUID
328334
*/
329335
public static GUID v7() {
336+
330337
final long time = System.currentTimeMillis();
331-
ThreadLocalRandom random = ThreadLocalRandom.current();
332-
final long msb = (time << 16) | (random.nextLong() & MASK_16);
333-
final long lsb = random.nextLong();
338+
339+
final long msb = (time << 16) | (LazyHolder.random() & MASK_16);
340+
final long lsb = LazyHolder.random();
341+
334342
return version(msb, lsb, 7);
335343
}
336344

@@ -476,6 +484,22 @@ private static long gregorian() {
476484
return time;
477485
}
478486

487+
private static class LazyHolder {
488+
489+
// The JVM unique number tries to mitigate the fact that the thread
490+
// local random is not seeded with a secure random seed by default.
491+
// Their seeds are based on temporal data and predefined constants.
492+
// Although the seeds are unique per JVM, they are not across JVMs.
493+
// It helps to generate different sequences of numbers even if two
494+
// ThreadLocalRandom are by chance instantiated with the same seed.
495+
// Of course it doesn't better the output, but doesn't hurt either.
496+
static final long JVM_UNIQUE_NUMBER = new SecureRandom().nextLong();
497+
498+
private static long random() {
499+
return ThreadLocalRandom.current().nextLong() ^ JVM_UNIQUE_NUMBER;
500+
}
501+
}
502+
479503
private static GUID hash(int version, String algorithm, GUID namespace, String name) {
480504

481505
Objects.requireNonNull(name, "Null name");

0 commit comments

Comments
 (0)