< 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 >