第6条:期限切れのオブジェクトの参照をなくす

3932 ワード

まず、配列実装スタックの例を見てみましょう.
package chaper1;



import java.util.Arrays;

import java.util.EmptyStackException;



public class Stack_Test00 {

    private Object[] elements;

    private static int size = 0;

    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    

    public Stack_Test00(){

        elements = new Object[DEFAULT_INITIAL_CAPACITY];

    }

    

    public void push(Object e){

        ensureCapacity();

        elements[size++] = e;

    }

    

    public Object pop(){

        if(size == 0)

            throw new EmptyStackException();

        return elements[--size];

    }

    

    /**

     *  , 

     */

    private void ensureCapacity(){

        if(elements.length == size){

            elements = Arrays.copyOf(elements, 2 * size);

        }

    }

}

 
表面的にはこのコードに誤りはないが,ゴミ回収器の活動が増加したり,メモリの消費が増加したりするにつれて,プログラム性能の低下が徐々に現れる.極端な場合、このメモリの漏洩はディスク交換(Disk Paging)を招き、プログラムの失敗(OutOfMemoryErrorエラー)を招くこともありますが、この失敗は比較的少ないです.
このメモリコードのメモリ漏洩の主な原因は、1つのスタックが先に成長した後に収縮すると、戦中のpopから出た要素はゴミ回収と見なされず、タイムリーなプログラムはそれを引用しないことにある.
これは、スタック内部でこれらのオブジェクトへの期限切れの参照(obsolete reference)が維持されているためです.期限切れの引用とは、永遠に引用が解除されず、引用が解除されなければ回収されないことを意味する.
このような期限切れの参照を解消するには、無効になったときにnullに設定するのが最善の方法です.
public Object pop(){

        if(size == 0)

            throw new EmptyStackException();

        Object result = elements[--size];

        elements[size] = null;

        return result;

}

しかし、オブジェクトを空にするのは規範ではなく手段であることを知っておく必要があります.
リファレンスを除去する最善の方法は、変更量を含むリファレンスをライフサイクルを終了させることです.最適な方法は、最もコンパクトな役割ドメインの範囲内で各変数を定義することです.
 
———————————————————————————————————————————————————————————————————————————————
 
上記の例では、メモリ漏洩の最も主要な原因は、このクラスが管理メモリを自分で管理することです.