首页 > 代码库 > 指向对象的引用置空---与内存泄漏

指向对象的引用置空---与内存泄漏

import java.util.Arrays;public class Stack {        private static final int INIT_SIZE = 10;    private Object[] datas;        private int size;    public Stack() {        super();        datas = new Object[INIT_SIZE];    }        public void push(Object data){        if (size == datas.length) {            extend();        }        datas[size++] = data;    }        public Object pop(){        if (size == 0) {            throw new IndexOutOfBoundsException("size is zero");        }        return datas[--size];    }        private void extend(){        datas = Arrays.copyOf(datas, 2 * size + 1);    }    }

上述代码,是从其他博客拷贝过来的。

上述代码的意思:

1.入栈,将指向某个对象的引用值,存放进来。

2.出栈,将指向某个对象的引用值,返回给用户。

潜在的问题:

    public Object pop(){        if (size == 0) {            throw new IndexOutOfBoundsException("size is zero");        }        return datas[--size];    }    

   这段代码的含义是,返回指向某个对象的引用值,然后,将栈顶向下移动。虽然是返回了某个对象的引用值,但是,数组中依然还保留着被返回的对象的引用值。这样的话,如果没有再进行入栈操作(用指向新的对象的引用值覆盖掉),那么,数组中就依然保留着被返回对象的引用值。

      而用户会觉得,既然某个对象已经出栈了,那么,该对象就不会还在栈中。而实际上,该对象还是在的,因为,datas数组中依然保留着指向该对象的引用值。如此,如果用户不再使用Stack进行入栈操作,那么,Stack就会一直保留着指向该对象的引用值。

       从而,也就出现了内存泄漏。对象依然存在在堆中,但用户并不知道,也不知道如何通过引用使用它。

       解决办法:每次返回某个指向对象的引用时,顺便将数组中保留的引用值置空,这样数组中就没有保存返回的对象引用值了。这样,GC在进行回时,就可以将该对象从堆中移除。

public Object pop(){        if (size == 0) {            throw new IndexOutOfBoundsException("size is zero");        }        Object data = datas[--size];        datas[size] = null;        return data;    }

 

    

 

        下面用具体例子展示:

        这样执行之后,用户以为stack中,已经没有指向a对象的引用了,实际上,还是有的。所以,堆上依然保留着a对象。

public static void main(String[] args){    Object a = new Object();     Stack stack = new Stack();     stack.push(a);     stack.pop();           a = null;}