package test;
import java.util.Arrays;
import java.util.EmptyStackException;
// 内存泄露问题
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
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+1);
}
}
分析:
当我们调用pop方法是,该方法将返回当前栈顶的elements,同时将该栈的活动区间(size)减一,然而此时被弹出的Object仍然保持至少两处引用,一个是返回的对象,另一个则是该返回对象在elements数组中原有栈顶位置的引用。这样即便外部对象在使用之后不再引用该Object,那么它仍然不会被垃圾收集器释放,久而久之导致了更多类似对象的内存泄露。修改如下:
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; //手工将数组中的该对象置空
return result;
}
由于现有的Java垃圾收集器已经足够只能和强大,因此没有必要对所有不在需要的对象执行obj = null的显示置空操作,这样反而会给程序代码的阅读带来不必要的麻烦,该条目只是推荐在以下3中情形下需要考虑资源手工处理问题:
1) 类是自己管理内存,如例子中的Stack类。
2) 使用对象缓存机制时,需要考虑被从缓存中换出的对象,或是长期不会被访问到的对象。
3) 事件监听器和相关回调。用户经常会在需要时显示的注册,然而却经常会忘记在不用的时候注销这些回调接口实现类。
转自: http://www.cnblogs.com/stephen-liu74/archive/2012/01/13/2228354.html