java – 引用数组索引是否会产生内存泄漏?
我正在阅读Effective
Java第二版的“第6项:消除过时的对象引用”.
以下是代码段. //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); } } 根据这个项目,内存泄漏是因为在弹出之后,数组索引没有被引用为NULL,如下所示: public Object pop() { if (size == 0) throw new EmptyStackException(); Object result = elements[--size]; elements[size] = null; // Eliminate obsolete reference return result; } 我的理解是假设对于给定的数组,我已经完成了元素[0] = new Object()然后我再次执行这个元素[0] = new Object()然后我的第一个对象将有资格进行垃圾收集,因为0th我的数组的索引不再指向它. 我的理解不正确吗?如果它是正确的,那么它如何在Effective Java中显示为内存泄漏. 解决方法
你得到了大部分.
如果你这样做: elements[0] = someOtherObject; 那么存储在索引0的另一个元素不再被引用并且可能被收集. 但是第一个pop()实现保留了该引用 – 它只减少了存储元素的“计数器”.因此,仍然引用该对象 – 并且在将新对象添加到堆栈之前不会收集该对象! 由于pop()的第二个版本中的注释明确指出 – 必须消除引用以确保堆栈不保留对该对象的引用.该对象应该被弹出 – 因此堆栈不应该保留有关该被删除对象的知识! 并确认提交:是的,当一个推送n个对象,然后推送n个其他对象,然后你没有内存泄漏 – 因为底层数组引用将全部更新并指向新对象.是的,如果弹出后推送的对象少于n个,则会保留过时的引用并阻止垃圾收集. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |