Comment on JDK-826722: SoftReference not cleared on OutOfMemoryError: Requested array size exceeds VM limit

Mandy Chung mandy.chung at oracle.com
Fri Jun 4 19:16:43 UTC 2021


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