--- old/src/java.base/share/classes/java/util/Properties.java 2018-06-15 13:39:42.000000000 -0700 +++ new/src/java.base/share/classes/java/util/Properties.java 2018-06-15 13:39:41.000000000 -0700 @@ -49,6 +49,8 @@ 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 @@ -156,8 +158,11 @@ * simple read operations. Writes and bulk operations remain synchronized, * as in Hashtable. */ - private transient ConcurrentHashMap map; + private transient final ConcurrentHashMap 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. * @@ -1473,7 +1478,7 @@ @Override public synchronized Object clone() { Properties clone = (Properties) cloneHashtable(); - clone.map = new ConcurrentHashMap<>(map); + UNSAFE.putObjectVolatile(clone, MAP_OFFSET, new ConcurrentHashMap<>(map)); return clone; } @@ -1537,13 +1542,14 @@ .checkArray(s, Map.Entry[].class, HashMap.tableSizeFor((int)(elements / 0.75))); // create CHM of appropriate capacity - map = new ConcurrentHashMap<>(elements); + ConcurrentHashMap 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); } }