Skip to content

Commit

Permalink
8281631: HashMap copy constructor and putAll can over-allocate table
Browse files Browse the repository at this point in the history
Reviewed-by: smarks
  • Loading branch information
XenoAmess authored and Stuart Marks committed Mar 16, 2022
1 parent 0cf291b commit 3e39304
Show file tree
Hide file tree
Showing 4 changed files with 258 additions and 72 deletions.
14 changes: 7 additions & 7 deletions src/java.base/share/classes/java/util/HashMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -495,9 +495,9 @@ final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
int s = m.size();
if (s > 0) {
if (table == null) { // pre-size
float ft = ((float)s / loadFactor) + 1.0F;
int t = ((ft < (float)MAXIMUM_CAPACITY) ?
(int)ft : MAXIMUM_CAPACITY);
double dt = Math.ceil(s / (double)loadFactor);
int t = ((dt < (double)MAXIMUM_CAPACITY) ?
(int)dt : MAXIMUM_CAPACITY);
if (t > threshold)
threshold = tableSizeFor(t);
} else {
Expand Down Expand Up @@ -1527,12 +1527,12 @@ private void readObject(ObjectInputStream s)
} else if (mappings == 0) {
// use defaults
} else if (mappings > 0) {
float fc = (float)mappings / lf + 1.0f;
int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
double dc = Math.ceil(mappings / (double)lf);
int cap = ((dc < DEFAULT_INITIAL_CAPACITY) ?
DEFAULT_INITIAL_CAPACITY :
(fc >= MAXIMUM_CAPACITY) ?
(dc >= MAXIMUM_CAPACITY) ?
MAXIMUM_CAPACITY :
tableSizeFor((int)fc));
tableSizeFor((int)dc));
float ft = (float)cap * lf;
threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
(int)ft : Integer.MAX_VALUE);
Expand Down
10 changes: 4 additions & 6 deletions src/java.base/share/classes/java/util/WeakHashMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,7 @@ public WeakHashMap(int initialCapacity, float loadFactor) {
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal Load factor: "+
loadFactor);
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1;
int capacity = HashMap.tableSizeFor(initialCapacity);
table = newTable(capacity);
this.loadFactor = loadFactor;
threshold = (int)(capacity * loadFactor);
Expand Down Expand Up @@ -251,7 +249,7 @@ public WeakHashMap() {
* @since 1.3
*/
public WeakHashMap(Map<? extends K, ? extends V> m) {
this(Math.max((int) ((float)m.size() / DEFAULT_LOAD_FACTOR + 1.0F),
this(Math.max((int) Math.ceil(m.size() / (double)DEFAULT_LOAD_FACTOR),
DEFAULT_INITIAL_CAPACITY),
DEFAULT_LOAD_FACTOR);
putAll(m);
Expand Down Expand Up @@ -468,7 +466,7 @@ public V put(K key, V value) {
modCount++;
Entry<K,V> e = tab[i];
tab[i] = new Entry<>(k, value, queue, h, e);
if (++size >= threshold)
if (++size > threshold)
resize(tab.length * 2);
return null;
}
Expand Down Expand Up @@ -557,7 +555,7 @@ public void putAll(Map<? extends K, ? extends V> m) {
* to at most one extra resize.
*/
if (numKeysToBeAdded > threshold) {
int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
int targetCapacity = (int)Math.ceil(numKeysToBeAdded / (double)loadFactor);
if (targetCapacity > MAXIMUM_CAPACITY)
targetCapacity = MAXIMUM_CAPACITY;
int newCapacity = table.length;
Expand Down
1 change: 1 addition & 0 deletions test/jdk/ProblemList.txt
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java 8151492 generic-
java/lang/invoke/LFCaching/LFGarbageCollectedTest.java 8078602 generic-all
java/lang/invoke/lambda/LambdaFileEncodingSerialization.java 8249079 linux-x64
java/lang/invoke/RicochetTest.java 8251969 generic-all
java/lang/Enum/ConstantDirectoryOptimalCapacity.java 8282120 generic-all

############################################################################

Expand Down

1 comment on commit 3e39304

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.