JDK-8186958 - Behaviour of large values for numMapping in WeakHashMap.newWeakHashMap API

Jaikiran Pai jai.forums2013 at gmail.com
Mon Jun 6 07:01:47 UTC 2022


In a recent enhancement we added new APIs to construct LinkedHashMap, 
HashMap and WeakHashMap instances as part of 
https://bugs.openjdk.java.net/browse/JDK-8186958.

Since we missed adding tests for that change, I have been working on 
adding some basic tests for this change as part of 
https://bugs.openjdk.java.net/browse/JDK-8285405. The draft PR is here 
https://github.com/openjdk/jdk/pull/9036.

It's in draft state because it has uncovered an aspect of this change 
that we might have to address or document for these new APIs. 
Specifically, the tests I added now have a test which does the 
equivalent of:

// numMappings = 2147483647
var w = WeakHashMap.newWeakHashMap(Integer.MAX_VALUE);

Similar tests have been added for HashMap and LinkedHashMap too, but for 
the sake of this discussion, I'll focus on WeakHashMap. Running this 
code/test runs into:

test NewWeakHashMap.testNewWeakHashMapNonNegative(2147483647): failure
java.lang.OutOfMemoryError: Java heap space
     at java.base/java.util.WeakHashMap.newTable(WeakHashMap.java:194)
     at java.base/java.util.WeakHashMap.<init>(WeakHashMap.java:221)
     at java.base/java.util.WeakHashMap.<init>(WeakHashMap.java:238)
     at 
java.base/java.util.WeakHashMap.newWeakHashMap(WeakHashMap.java:1363)
     at NewWeakHashMap.testNewWeakHashMapNonNegative(NewWeakHashMap.java:69)


This exception happens with only WeakHashMap. LinkedHashMap and HashMap 
don't show this behaviour. It appears that WeakHashMap eagerly creates 
an large array (of length 1073741824 in this case) in the newTable 
method which gets called by its constructor.

This raises a few questions about these new APIs - these APIs take an 
integer and the document allows positive values. So the current 
Integer.MAX_VALUE in theory is a valid integer value for this API. 
Should these APIs document what might happen when such a large 
numMapping is passed to it? Should that documentation be different for 
different classes (as seen the HashMap and LinkedHashMap behave 
differently as compared to WeakHashMap)? Should this "numMappings" be 
considered a hard value? In other words, the current documentation of 
this new API states:

"Creates a new, empty WeakHashMap suitable for the expected number of 
mappings
....
and its initial capacity is generally large enough so that the expected 
number
of mappings can be added without resizing the map."

The documentation doesn't seem to guarantee that the resizing won't 
occur. So in cases like these where the numMappings is a very large 
value, should the implementation(s) have logic which doesn't trigger 
this OOM error?

-Jaikiran




More information about the core-libs-dev mailing list