7071826: Avoid benign race condition in initialization of UUID
authormduigou
Fri, 11 May 2012 11:31:46 -0700
changeset 12690 a2d28a91f9b7
parent 12689 35cbede4f958
child 12691 88de2d4d5084
7071826: Avoid benign race condition in initialization of UUID Summary: Avoids mostly benign but sometimes expensive race condition on initialization of UUID.numberGenerator which is used by UUID.randomUUID() Reviewed-by: alanb, chegar
jdk/src/share/classes/java/util/UUID.java
jdk/test/java/util/UUID/UUIDTest.java
--- a/jdk/src/share/classes/java/util/UUID.java	Fri May 11 10:09:18 2012 +0100
+++ b/jdk/src/share/classes/java/util/UUID.java	Fri May 11 11:31:46 2012 -0700
@@ -90,9 +90,11 @@
 
     /*
      * 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 @@
      * @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 @@
      * 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&nbsp;RFC&nbsp;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 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)))
--- a/jdk/test/java/util/UUID/UUIDTest.java	Fri May 11 10:09:18 2012 +0100
+++ b/jdk/test/java/util/UUID/UUIDTest.java	Fri May 11 11:31:46 2012 -0700
@@ -58,6 +58,12 @@
         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 @@
         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);
         }
     }