SoftReference incorrect javadoc?

Bernd Eckenfels ecki at zusammenkunft.net
Wed Apr 17 04:01:33 UTC 2019


Your test code does not fail because of the SoftRef but because of the Finalizer I think. But it’s good to know that 11 handles this better.

--
https://Bernd.eckenfels.net

________________________________
Von: Michael Pollmeier <michael at michaelpollmeier.com>
Gesendet: Mittwoch, April 17, 2019 5:54 AM
An: jdk-dev at openjdk.java.net
Cc: ecki at zusammenkunft.net
Betreff: Re: SoftReference incorrect javadoc?

Looks like the mailing list removed the attachment. It's short enough to
be in the email body.

SoftRefTest.java:
```
import java.lang.ref.SoftReference;
import java.util.ArrayList;

public class SoftRefTest {
static final int count = 2000000;

public static void main(String[] args) throws Exception {
ArrayList<SoftReference<Instance>> instances = new ArrayList<>();
long start = System.currentTimeMillis();

for (int i = 0; i<count; i++) {
instances.add(new SoftReference<>(new Instance()));

if (i % 100000 == 0 && i > 0) {
Thread.sleep(100); // give GC time to breathe
System.out.println(i + " instances created; free=" +
Runtime.getRuntime().freeMemory() / 1024 / 1024 + "M");
}
}

System.out.println("time taken: " + (System.currentTimeMillis() -
start));
}

}

class Instance {
static int finalizedCount = 0;
String[] occupySomeHeap = new String[50];

@Override
protected void finalize() throws Throwable {
super.finalize();
finalizedCount++;
if (finalizedCount % 100000 == 0) {
System.out.println(finalizedCount + " instances finalized");
}
}
}
```

On 17/04/19 1:59 pm, Michael Pollmeier wrote:
> Hi Per,
>
> While testing different JVMs I realized that it's fixed in openjdk 11,
> e.g. openjdk version "11.0.1" 2018-10-16 LTS (zulu build), maybe by this
> commit: https://hg.openjdk.java.net/jdk/jdk/rev/6464882498b5
> That's great to know, but is it worth updating the javadocs of older
> versions?
>
> To reproduce it I attached a simple SoftRefTest.java to easily reproduce
> it. It allocates (only) softly referenced objects that occupy some heap,
> occasionally printing counts (instantiated, finalized, free heap).
>
> Usage:
> javac SoftRefTest.java
> java -Xms256m -Xmx256m SoftRefTest
>
> Output:
> 100000 instances created; free=212M
> 200000 instances created; free=181M
> 300000 instances created; free=152M
> 400000 instances created; free=121M
> 500000 instances created; free=93M
> 600000 instances created; free=61M
> 700000 instances created; free=33M
> Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
> at Instance.<init>(SoftRefTest.java:27)
> at SoftRefTest.main(SoftRefTest.java:12)
>
> Interpretation:
> It doesn't free any of the only softly referenced objects, resulting in
> an OutOfMemoryError, contradicting the 'guarantee' in the javadoc.
>
> Workaround: if you additionally configure
> `-XX:SoftRefLRUPolicyMSPerMB=0`, it finalizes them and doesn't run out
> of memory.
>
> Tested with:
> openjdk version "1.8.0_212"
> java version "1.8.0_144" (oracle)
> openjdk version "9.0.4.1" (zulu build)
> openjdk version "10.0.2" 2018-07-17 (zulu build)
>
> Cheers
> Michael
>
>
> On 16/04/19 6:27 pm, Per Liden wrote:
>> Hi Michael,
>>
>> On 4/16/19 4:19 AM, David Holmes wrote:
>>> Hi Michael,
>>>
>>> Re-directing to core-libs-dev and hotspot-gc-dev.
>>>
>>> Thanks,
>>> David
>>>
>>> On 16/04/2019 12:14 pm, Michael Pollmeier wrote:
>>>> Quoting
>>>> https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/SoftReference.html
>>>>
>>>>
>>>>
>>>>> All soft references to softly-reachable objects are guaranteed to have
>>>> been cleared before the virtual machine throws an OutOfMemoryError
>>>>
>>>> That statement was true when soft references were first introduced in
>>>> java 1.2, but from java 1.3.1 the jvm property
>>>> `-XX:SoftRefLRUPolicyMSPerMB` was introduced.
>>
>> That statement is still true. When the GC gets into a situation where it
>> is having trouble satisfying an allocation, then SoftRefLRUPolicyMSPerMB
>> will be ignored and all soft references will be cleared, before the GC
>> gives up and throws an OOME.
>>
>>>> It defaults to 1000 (milliseconds), meaning that if there’s only 10MB
>>>> available heap, the garbage collector will free references that have
>>>> been used more than 10s ago. I.e. everything else (including young
>>>> softly reachable objects) will *not* be freed, leading to an
>>>> OutOfMemoryError, contradicting the above quoted 'guarantee'.
>>>>
>>>> That's also the behaviour I observed on various JREs. Would you agree,
>>>> i.e. should I propose an updated doc?
>>
>> Could you elaborate on what kind of test you did to come to this
>> conclusion? Preferably provide a re-producer. In OOME situations, if a
>> SoftReference isn't cleared, it is typically because you have
>> unknowingly made it strongly reachable.
>>
>> cheers,
>> Per
>>
>



More information about the jdk-dev mailing list