私はJavaとそのメモリリークを許容する能力について少し実験を行っています。私はこの簡単なコードを書きました:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
class Obj {
int i;
Obj(int i) {
this.i = i;
}
}
List<Obj> list;
while(true) {
list = new ArrayList<Obj>();
for(int i = 0; i < 1000; i++) {
Obj o = new Obj(i);
list.add(o);
}
try {
Thread.sleep(1); //<-- added to give the gc time to trash the previous iteration
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
これを実行すると(特に、反復ごとにリストに追加されるオブジェクトが増えると)、使用されるメモリの量が急速に増加するのを確認できます。反復ごとに10000個のオブジェクトが追加され、2ギガバイトにすばやく到達することができました。リスト(および関数のような「リンクリスト」リストを利用する他のタイプのオブジェクト)は削除されたくないように見えます。
オブジェクトをリストに追加しなかった場合、メモリヒープはまったく増加しませんでした(つまり、ごみ処理がその役割を果たしていました)。反復ごとにリストをnullにリセットしてから、リストを再宣言し、clear()メソッドを呼び出してみました。何も機能していないようです。ループでリストを使用するときはいつでも、RAMが助けを求めて叫びます。
では、なぜこれが発生するのでしょうか。なぜゴミ処理は、リストを積み上げるのではなく、反復ごとにリストを削除しないのですか?リストインターフェイスでは、この種の使用は許可されていませんか?最後のインスタンスを取り除くのに十分な時間をゴミ処理に与えていないだけですか?