Comment on JDK-826722: SoftReference not cleared on OutOfMemoryError: Requested array size exceeds VM limit
Raffaello Giulietti
raffaello.giulietti at gmail.com
Fri Jun 4 20:24:33 UTC 2021
Hi Mandy,
the OOME thrown for VM limits reasons is not related to any purported
heap exhaustion but to the VM refusing to allocate an array of size
Integer.MAX_VALUE or Integer.MAX_VALUE - 1, *even* if there's plenty of
space.
For example, with 8 GiB of heap and a size of Integer.MAX_VALUE - 2 the
small program runs without fuss:
java -XX:+UseG1GC -Xms8g -Xmx8g -cp ... Softly 2147483645
But when the argument is increased by 1 to Integer.MAX_VALUE - 1
java -XX:+UseG1GC -Xms8g -Xmx8g -cp ... Softly 2147483646
you immediately get:
Exception in thread "main" java.lang.AssertionError: non-null referent
at Softly.main(Softly.java:26)
Caused by: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at Softly.main(Softly.java:15)
In other words, OOME is "abused" in such cases. A VM limit error should
really throw another kind of error, not OOME, because contrary to its
name there's not necessarily a lack of memory space, as shown here.
To parallel current behavior, thus, the spec should be amended as
proposed "... an OutOfMemoryError caused by Java heap space exhaustion."
or a similar wording.
Alternatively, to maintain the current spec untouched, the VM should
throw another kind of error for VM limits. Not sure if this has any
adverse impact on existing code in the wild.
Greetings
Raffaello
On 2021-06-04 21:16, Mandy Chung wrote:
> I'm not sure if the spec should be updated. JDK-8267222 needs the GC
> team to evaluate.
>
> I have added my comment in this JBS issue.
>
> The SoftReference spec has the guarantee:
> “All soft references to softly-reachable objects are guaranteed to
> have been cleared before the virtual machine throws an OutOfMemoryError.”
>
> This is a reasonable guarantee expected by design in response to memory
> demand.
>
> For the OOME thrown due to "requested array size exceeds VM limit", it
> seems that this is a fast-path throwing OOME without really going
> through the object allocation request (where reference processing will
> be performed in GC cycle).
>
> The question to the GC team is whether VM implementation can and should
> support this soft reference guarantee. Note that the soft reference
> objects are cleared as specified, the large object allocation exceeding
> VM limit would fail any way. If the implementation is feasible, I'm
> inclined to clear the soft reference objects when OOME is thrown as
> specified even the object allocation request is known to fail.
>
> Mandy
>
> On 6/3/21 11:57 AM, Raffaello Giulietti wrote:
>> Hi,
>>
>> upon reading [1] I tried a similar scenario, but where OOME are caused
>> by "Java heap space" exhaustion rather than by VM limits.
>>
>>
>> import java.lang.ref.SoftReference;
>> import java.text.DecimalFormat;
>> import java.util.ArrayList;
>>
>> public class Softly {
>>
>> public static void main(String[] args) {
>> var size = Integer.parseInt(args[0]);
>> var format = new DecimalFormat("#,###");
>> var news = 0;
>> var ref = new SoftReference<>(new ArrayList<>());
>> for (;;) {
>> byte[] b = null;
>> try {
>> b = new byte[size];
>> ++news;
>> ref.get().add(b);
>> } catch (NullPointerException __) {
>> System.out.format("totSize = %20s, allocations =
>> %d\n", format.format((long) news * size), news);
>> ref = new SoftReference<>(new ArrayList<>());
>> ref.get().add(b);
>> } catch (OutOfMemoryError e) {
>> if (ref.refersTo(null)) {
>> throw new AssertionError("allocations =
>> %d".formatted((news)), e);
>> }
>> throw new AssertionError("non-null referent", e);
>> }
>> }
>> }
>>
>> }
>>
>>
>> E.g.,
>> java -XX:+UseG1GC -Xms1g -Xmx1g -cp ... Softly 800000000
>>
>>
>> Depending on the collector and how tight the heap is, I sometimes
>> observe a "Java heap space" OOME but then the referent of ref is null.
>> I never observed a OOME with a non-null referent for ref. Hence, in
>> scenarios where OOME are caused by heap exhaustion, soft refs seem to
>> work as advertised.
>>
>> Tried on AdoptOpenJDK-16.0.1+9 with SerialGC, ParallelGC, G1GC, ZGC
>> and ShenandoahGC with either -Xms1g/-Xmx1g or -Xms2g/-Xmx2g (small
>> heaps) and various byte[] sizes.
>>
>> Thus, the current wording in SoftReference's javadoc:
>>
>> "All soft references to softly-reachable objects are guaranteed to
>> have been cleared before the virtual machine throws an OutOfMemoryError."
>>
>> could be amended to read:
>>
>> "All soft references to softly-reachable objects are guaranteed to
>> have been cleared before the virtual machine throws an
>> OutOfMemoryError caused by Java heap space exhaustion."
>>
>>
>> Greetings
>> Raffaello
>>
>> ----
>>
>> [1] https://bugs.openjdk.java.net/browse/JDK-8267222
>
More information about the core-libs-dev
mailing list