< prev index next >
src/java.base/share/classes/java/util/Properties.java
Print this page
rev 50605 : 8199435: Unsafe publication of java.util.Properties.map
Reviewed-by: dholmes, psandoz, plevart, redestad
@@ -146,19 +146,19 @@
* A property list that contains default values for any keys not
* found in this property list.
*
* @serial
*/
- protected Properties defaults;
+ protected volatile Properties defaults;
/**
* 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 volatile ConcurrentHashMap<Object, Object> map;
/**
* Creates an empty property list with no default values.
*
* @implNote The initial capacity of a {@code Properties} object created
@@ -1095,11 +1095,12 @@
* @see #defaults
*/
public String getProperty(String key) {
Object oval = map.get(key);
String sval = (oval instanceof String) ? (String)oval : null;
- return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
+ Properties defaults;
+ return ((sval == null) && ((defaults = this.defaults) != null)) ? defaults.getProperty(key) : sval;
}
/**
* Searches for the property with the specified key in this property list.
* If the key is not found in this property list, the default property list,
@@ -1481,10 +1482,11 @@
// Hashtable serialization overrides
// (these should emit and consume Hashtable-compatible stream)
@Override
void writeHashtable(ObjectOutputStream s) throws IOException {
+ var map = this.map;
List<Object> entryStack = new ArrayList<>(map.size() * 2); // an estimate
for (Map.Entry<Object, Object> entry : map.entrySet()) {
entryStack.add(entry.getValue());
entryStack.add(entry.getKey());
@@ -1535,15 +1537,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);
+ var map = 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);
}
+ this.map = map;
}
}
< prev index next >