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?
Even if your code does not (seem to) access
longArr
anywhere at compile time, it could still be accessed at any time by reflection, and this is something that the GC/JIT compiler cannot guess.The only unused variables that could be removed are the local ones (whose reference can be cleared as soon as they are assigned). In fact, the Eclipse compiler even allows to remove them at compile time (see Preferences > Java > Compiler > Preserve unused local variables).
longArr is not used anywhere; but you are creating objects of your class MemoryTest. This means attribute longArr is getting initialized for each object.
So if reference to an object of your class is not null; then don't think there is any way to GC this attribute. longArr will always be tied through objects; so it can get cleaned up only when object gets GCed.