`
aqxyjay
  • 浏览: 3824 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

EJ.06 消除过期的对象引用

    博客分类:
  • EJ
EJ 
阅读更多
  • Java语言也需要考虑内存管理
//Can u spot the "memory leak"?
public class Stack {
    private Ojbect[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    public Stack(int initialCapacity) {
        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) {
            Object[] oldElements = elements;
            elements = Arrays.copyOf(elements, 2 * size + 1);
        }
    }
}

以上代码存在内存溢出的风险:如果一个栈是先增长,然后再收缩,栈中pop谈出来的对象不会被当作垃圾回收。因为栈内部维护着这些对象的过期引用(obsolete reference)。

  

  • 一旦对象引用已经过期,只需清空这些引用即可
    public Object pop() {
        if (size == 0)
            throw new EmptyStackException();
        Object result = elements[--size];
        elements[size] = null;
        return result;
    }

  • 消除过期引用最好的方法是让包含该引用的变量结束其生命周期
遗留任务:学习EJ.45时,在最紧凑的作用域范围内定义每一个变量,以上情景会自然而然地发生。
  • 只要类是自己管理内存,就应该警惕内存泄露问题
  • 内存泄露的另一个常见来源是缓存(EJ p23)
  • 内存泄露的第三个常见来源是监听器和其他回调
遗留任务:确认这句话,并写Demo来验证。“确保回调立即被当作垃圾回收的最佳方法是只保存它们的弱引用(weak reference)”。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics