Java SoftReference Warranty Not Working

The JDK 7 documentation talks about SoftReference :

"All soft links to objects with soft achievement are guaranteed before the virtual machine throws an OutOfMemoryError. "

However, in my test program, I see an OutOfMemoryError sequentially (except for the Stranger section below):

 // RefObjectTest.java import java.util.*; import java.lang.ref.*; public class RefObjectTest { public static void main(String[] args) { ArrayList<byte[]> leaks = new ArrayList<>(); byte[] obj = new byte[10 * 1024 * 1024]; SoftReference<byte[]> ref = new SoftReference<>(obj); // WeakReference is supposed to be eagerly GC'ed, but I see no // difference in terms of program behavior: still get OOME. // // WeakReference<byte[]> ref = new WeakReference<>(obj); obj = null; while(true) { byte[] x = ref.get(); if(x == null) { System.out.println("Referent stands garbage collected!!"); break; } else { System.out.println("Referent still alive."); } // Leak memory in small, 10k increments. If soft reference // worked the way it advertized, then just before the OOME, the // 10MB referent should have been GC'ed to accomodate this small // 10K new memory request. But it doesn't appear to work that way! // try { leaks.add(new byte[10 * 1024]); // } catch(OutOfMemoryError e) { // System.out.println(ref.get() == null ? "Referent cleared" : // "Referent still alive"); // } // VERY STRANGE: If I re-instate the above try-catch block, then no OOME is // thrown, and the program keeps printing "Referent still alive" lines // forever until I finally kill it with a Ctrl+C. // Uncommenting gc() tends to delay the OOME in terms of time, // but OOME eventually does happen, and after the same number of // iterations of this loop. // // System.gc(); } } } 

Here's the conclusion:

 $ java -Xmx15m RefObjectTest Referent still alive. ... Referent still alive. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at RefObjectTest.main(RefObjectTest.java:38) 

Stranger

What is VERY STRANGE, if I run the try-catch block again, the program seems to work fine forever by typing "The referent is still alive." lines until I get tired and kill him.

 $ java -version java version "1.7.0_45" Java(TM) SE Runtime Environment (build 1.7.0_45-b18) Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode) $ $ uname -a Linux ida 3.10.11-100.fc18.x86_64 #1 SMP Mon Sep 9 13:06:31 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux 

What am I missing in all of this?

+6
source share
1 answer

This is not strange, the distribution does not work, which throws an exception. If you catch an exception, you say that the program can continue without catching the exception, you say that you cannot handle it, and the program will exit.

Inside the while loop you do:

  byte[] x = ref.get(); 

This creates a new strong link from your Soft Reference. Once you do this, he is no longer entitled to collect. You will not clear this Strong link before performing a new selection.

Make x = null after running the test.

+4
source

All Articles