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 廃れたオブジェクトの参照を取り除く