次のクラスを検討してください。
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
}
}
これは次のように失敗します。
... 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)
longArr
明らかにこれは不自然な例ですが、GC/JIT コンパイラーがどこにも使用されていないこのオブジェクトを片付けることができるかどうか疑問に思っていました。Java 7 の時点では、これを整理していないようですが、コンパイラがよりスマートになるか、何らかの方法で例を変更すると、これが発生する可能性がありますか、それとも JVM によって契約上禁止されていますか?