オブジェクトに最初に割り当てられたメモリ空間を、そのオブジェクトが使われなくなった時(そのオブジェクトへの参照がなくなった時)に、JavaVM がそのオブジェクトが占有していたメモリ空間を自動的に解放する。
GCされない例/される例
GCされない例
class Dept { // 部署クラス
private Emp[] emps; // 所属する従業員
private int size;
public Dept() {
emps = new Emp[10]; // 従業員の席を用意
}
public void employ(Emp emp) { // 従業員を雇う
if(emps.length == size) {
emps = Arrays.copyOf(emps, 2 * size + 1); // 定員オーバーになったら、席を追加
}
emps[size++] = emp;
}
public void fire(int index) { // 従業員を解雇する
Emp emp = emps[index];
emp.empNo = -1;
}
public int getEmpsSize() {
return size;
}
}
OutOfMemoryErrorを発生させる
public static final void main(String[] args) {
Dept[] depts = new Dept[3456]; // 3456個部署作って・・・
int deptNo = 0;
int empNo = 0;
try {
while(deptNo < depts.length) {
Dept dept = new Dept();
depts[deptNo++] = dept;
for(int i = 0; i < 3456; i++) { // 3456人部署に雇って・・・
Emp emp = new Emp(deptNo, empNo++);
dept.employ(emp);
}
int empsSize = dept.getEmpsSize();
for(int i = 0; i < empsSize; i++) {
if((i % 2) == 0) { // 内、半分を解雇する
dept.fire(i);
}
}
}
} catch(OutOfMemoryError e) {
System.err.println("OutOfMemoryError");
} finally {
System.out.println("deptNo : " + deptNo + " empNo : " + empNo); // deptNo : 3332 empNo : 11514569
}
}
自分の環境だと、 3332個目の部署・11514569人目の従業員でOutOfMemoryErrorが発生する。
GCされる例
部署クラスのfire()メソッド内で、解雇された従業員にnullを設定するように変更する。
public void fire(int index) {
emps[index] = null; // nullを設定する
size--;
}
もう一度mainを実行すると、 「deptNo : 3456 empNo : 11943936」が出力されて、OutOfMemoryErrorはスローされずにプログラムが終了する。
そもそもこの部署クラスのように、プログラマーが独自にメモリー管理をしなれけばならないようなプログラムは、例外的であるべきだ、とEffective Javaには書いてあります。
see also:
Javaプログラマであるかを見分ける10の質問 4.オブジェクトがガベージコレクション(GC)される主たる条件は何か?
see also: Effective Java(第2版)第2章オブジェクトの生成と消滅 項目6 廃れたオブジェクトの参照を取り除く