7071826: Avoid benign race condition in initialization of UUID
Avoids mostly benign but sometimes expensive race condition on initialization of UUID.numberGenerator which is used by UUID.randomUUID() Reviewed-by: alanb, chegar
This commit is contained in:
parent
6e335b3720
commit
3b77eb7680
jdk
@ -90,9 +90,11 @@ public final class UUID implements java.io.Serializable, Comparable<UUID> {
|
||||
|
||||
/*
|
||||
* The random number generator used by this class to create random
|
||||
* based UUIDs.
|
||||
* based UUIDs. In a holder class to defer initialization until needed.
|
||||
*/
|
||||
private static volatile SecureRandom numberGenerator = null;
|
||||
private static class Holder {
|
||||
static final SecureRandom numberGenerator = new SecureRandom();
|
||||
}
|
||||
|
||||
// Constructors and Factories
|
||||
|
||||
@ -137,10 +139,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID> {
|
||||
* @return A randomly generated {@code UUID}
|
||||
*/
|
||||
public static UUID randomUUID() {
|
||||
SecureRandom ng = numberGenerator;
|
||||
if (ng == null) {
|
||||
numberGenerator = ng = new SecureRandom();
|
||||
}
|
||||
SecureRandom ng = Holder.numberGenerator;
|
||||
|
||||
byte[] randomBytes = new byte[16];
|
||||
ng.nextBytes(randomBytes);
|
||||
@ -255,7 +254,8 @@ public final class UUID implements java.io.Serializable, Comparable<UUID> {
|
||||
* The variant number has the following meaning:
|
||||
* <p><ul>
|
||||
* <li>0 Reserved for NCS backward compatibility
|
||||
* <li>2 The Leach-Salz variant (used by this class)
|
||||
* <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>
|
||||
* (Leach-Salz), used by this class
|
||||
* <li>6 Reserved, Microsoft Corporation backward compatibility
|
||||
* <li>7 Reserved for future definition
|
||||
* </ul>
|
||||
@ -265,7 +265,7 @@ public final class UUID implements java.io.Serializable, Comparable<UUID> {
|
||||
public int variant() {
|
||||
// This field is composed of a varying number of bits.
|
||||
// 0 - - Reserved for NCS backward compatibility
|
||||
// 1 0 - The Leach-Salz variant (used by this class)
|
||||
// 1 0 - The IETF aka Leach-Salz variant (used by this class)
|
||||
// 1 1 0 Reserved, Microsoft backward compatibility
|
||||
// 1 1 1 Reserved for future definition.
|
||||
return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62)))
|
||||
|
@ -58,6 +58,12 @@ public class UUIDTest {
|
||||
List list = new LinkedList();
|
||||
for (int i=0; i<100; i++) {
|
||||
UUID u1 = UUID.randomUUID();
|
||||
if (4 != u1.version()) {
|
||||
throw new Exception("bad version");
|
||||
}
|
||||
if (2 != u1.variant()) {
|
||||
throw new Exception("bad variant");
|
||||
}
|
||||
if (list.contains(u1))
|
||||
throw new Exception("random UUID collision very unlikely");
|
||||
list.add(u1);
|
||||
@ -70,10 +76,16 @@ public class UUIDTest {
|
||||
List list = new LinkedList();
|
||||
for (int i=0; i<100; i++) {
|
||||
byteSource.nextBytes(someBytes);
|
||||
UUID test = UUID.nameUUIDFromBytes(someBytes);
|
||||
if (list.contains(test))
|
||||
UUID u1 = UUID.nameUUIDFromBytes(someBytes);
|
||||
if (3 != u1.version()) {
|
||||
throw new Exception("bad version");
|
||||
}
|
||||
if (2 != u1.variant()) {
|
||||
throw new Exception("bad variant");
|
||||
}
|
||||
if (list.contains(u1))
|
||||
throw new Exception("byte UUID collision very unlikely");
|
||||
list.add(test);
|
||||
list.add(u1);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user