Consider the following class:
public class MemoryTest
{
private long[] longArr; // Eclipse marks this unused
public MemoryTest(int arrSize) {
longArr = new long[arrSize*10];
}
public static void main(String[] args) {
int numObjs = 10000;
MemoryTest[] mts = new MemoryTest[numObjs];
for(int i = 0; i < numObjs; i++) {
// build a large number of objects which hold expensive, unused references
mts[i] = new MemoryTest(i);
//System.gc(); interestingly, uncommenting this line causes OOM earlier
System.out.println("Built "+i+": "+Runtime.getRuntime().freeMemory()/1024+"KB");
}
System.out.println(Arrays.hashCode(mts)); // so elements cannot be GCed earlier
}
}
This fails like so:
... truncated output ...
Built 5236: 62070KB
Built 5237: 61661KB
Built 5238: 61252KB
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at MemoryTest.<init>(MemoryTest.java:6)
at MemoryTest.main(MemoryTest.java:15)
Obviously this is a contrived example, but I was wondering if the GC/JIT compiler could ever tidy up this object given that longArr
isn't used anywhere. As of Java 7 it seems to not tidy this up now, but if the compiler gets smarter or we change the example in some way could this ever happen, or is it contractually forbidden by the JVM?