美文网首页程序员
消除过期的对象引用

消除过期的对象引用

作者: DeppWang | 来源:发表于2017-07-06 09:46 被阅读0次

    你能看出以下代码哪里内存泄漏吗?

    // 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()方法存在内存泄漏。

    内存泄漏可以称为“ 无意识的对象保持(unintentional object retention)”。
    在pop()方法中从栈中弹出来的对象将不会被当做垃圾回收。栈内部维护着对这些对象的过期引用(obsolete reference)。所谓的过期引用,是指永远也不会再被解除的引用。凡是在elements数组的“活动部分”(active portion)之外的任何引用都是过期的。活动部分是指elements中下标小于size的那些元素。

    解决方法:上述述例子中的Stack类而言,只要一个单元被弹出栈,指向它的引用就过期了。一旦数组元素变成了非活动部分的一部分,就手工清空这些数组元素。修改后的pop()方法如下:

    public Object pop() {
        if (size == 0)
            throw new EmptyStackException();
        Object result = elements[--size];//result相当于一个temp。
        elements[size] = null; // Eliminate obsolete reference
        return result;
    }
    

    清空对象引用应该是一种例外,而不是一种规范行为。消除过期引用最好的方法是让包含该引用的变量结束其生命周期。

    延伸阅读

    length、size()、length()的区别:

    • 数组的长度(length):数组能容纳元素个数的值
    • 泛型集合的大小(size()):泛型中元素的个数
    • 字符串的长度(length()):字符的个数

    前缀递减和后缀递增:

    • 前缀递减,"--"操作符位于变量或表达式前,先执行运算,再生成值。如上例中elements[--size],size大小先减1,所以Object result = elements[--size];中result元素下标为size=size-1。
    • 后缀递增,"++"操作符位于变量或表达式后,先生成值,再执行运算。如上例中elements[size++] = e;,元素下标为size,再执行运算size=size+1。

    Arrays.copyOf()方法:

    • a copy of the original array, truncated or padded with nulls to obtain the specified length(原始数组的副本,缩短或填补null来获取指定的长度)。
    • 作用:如果数组元素的个数等于数组的长度,新建副本数组,将长度扩大为两倍加一,将数组副本赋值给elements。

    参考资料

    相关文章

      网友评论

        本文标题:消除过期的对象引用

        本文链接:https://www.haomeiwen.com/subject/zpachxtx.html