对《Effective Java》第6条原则中关于内存泄露的疑问。 Effective Java的第6条中提到,以下程序可能会引起内存泄露(原文引用:随着垃圾回收器活动的增加,或者由于内存占用的不断增加,程序性能的降低会逐渐表现出来。在极端的情况下,这种内存泄漏会导致磁盘分页,甚至导致程序失败,而出现OutOfMemoryError错误,但是这种失败情形相对比较少见): // Can you spot the "memory leak"? 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]; } /** * Ensure space for at least one more element, roughly * doubling the capacity each time the array needs to grow. */ private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); } }
泄露处在pop()函数中,--size后会导致大于size位置的elements依然被引用(即过期对象),从而不会被GC释放,解决方案是以下修改后的pop()函数: public Object pop() { if (size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; // Eliminate obsolete reference return result; }