天天看点

过期的对象引用消除过期的对象引用

消除过期的对象引用

修正前

public class Stack {

    public Object[] elements;
    
    public int size = 0;
    
    private static final int DEALULT_VLAUE = 16;

    public Stack() {
        elements = new Object[DEALULT_VLAUE];
    }

    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (size == 0) {
            throw new RuntimeException();
        }
        return elements[--size];
    }

    private void ensureCapacity() {
        if (elements.length == size) {
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }

}           

这段程序中并没有很明显的错误.无论如何测试,它都会成功通过每一项测试.

但是! 这段程序有一个"内存泄漏"

解析

// elements="Stack@539"
        Stack stack = new Stack();

        // elements[0]="1" size=1
        stack.push("1");

        // elements[0]="1" elements[1]="2" size=2
        stack.push("2");

        // elements[0]="1" elements[1]="2" size=1 pop="2"
        Object pop = stack.pop();

        // elements[0]="1" elements[1]="3" size=1
        stack.push("3");           

从上方可以看出如果pop后没有重新push那么elements对象还在引用已经删除的对象

内存泄漏-如果一个栈显示增长,然后再收缩,那么,从栈中弹出来的对象将不会被当做垃圾回收,即使使用的栈的程序不再引用这些对象,它们也不会被回收.这是因为,栈内部维护着对这些对象的过期引用.

过期引用-,是指永远也不会再被删除的引用.

修正后

public Object pop() {
        if (size == 0) {
            throw new RuntimeException();
        }
        Object result = elements[--size];
        elements[size] = null;
        return result;
    }           

// elements="Stack@539"
        Stack stack = new Stack();

        // elements[0]="1" size=1
        stack.push("1");

        // elements[0]="1" elements[1]="2" size=2
        stack.push("2");

        // elements[0]="1" size=1 pop="2"
        Object pop = stack.pop();

        // elements[0]="1" elements[1]="3" size=1
        stack.push("3");