< prev index next >

src/java.base/share/classes/java/util/Properties.java

Print this page

        

@@ -47,10 +47,12 @@
 import java.util.function.Function;
 
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.util.xml.PropertiesDefaultHandler;
 
+import jdk.internal.misc.Unsafe;
+
 /**
  * The {@code Properties} class represents a persistent set of
  * properties. The {@code Properties} can be saved to a stream
  * or loaded from a stream. Each key and its corresponding value in
  * the property list is a string.

@@ -154,12 +156,15 @@
      * Properties does not store values in its inherited Hashtable, but instead
      * in an internal ConcurrentHashMap.  Synchronization is omitted from
      * simple read operations.  Writes and bulk operations remain synchronized,
      * as in Hashtable.
      */
-    private transient ConcurrentHashMap<Object, Object> map;
+    private transient final ConcurrentHashMap<Object, Object> map;
 
+    private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+    private static final long MAP_OFFSET
+            = UNSAFE.objectFieldOffset(Properties.class, "map");
     /**
      * Creates an empty property list with no default values.
      *
      * @implNote The initial capacity of a {@code Properties} object created
      * with this constructor is unspecified.

@@ -1471,11 +1476,11 @@
     protected void rehash() { /* no-op */ }
 
     @Override
     public synchronized Object clone() {
         Properties clone = (Properties) cloneHashtable();
-        clone.map = new ConcurrentHashMap<>(map);
+        UNSAFE.putObjectVolatile(clone, MAP_OFFSET, new ConcurrentHashMap<>(map));
         return clone;
     }
 
     //
     // Hashtable serialization overrides

@@ -1535,15 +1540,16 @@
         // what is actually created.
         SharedSecrets.getJavaObjectInputStreamAccess()
                      .checkArray(s, Map.Entry[].class, HashMap.tableSizeFor((int)(elements / 0.75)));
 
         // create CHM of appropriate capacity
-        map = new ConcurrentHashMap<>(elements);
+        ConcurrentHashMap<Object,Object> tmpMap = new ConcurrentHashMap<>(elements);
 
         // Read all the key/value objects
         for (; elements > 0; elements--) {
             Object key = s.readObject();
             Object value = s.readObject();
-            map.put(key, value);
+            tmpMap.put(key, value);
         }
+        UNSAFE.putObjectVolatile(this, MAP_OFFSET, tmpMap);
     }
 }
< prev index next >