消除过期的对象引用

 

Java的垃圾回收确实帮助我们解决了不少内存管理的问题,但是,这并不意味着我们就可以完全依赖Java的垃圾回收。我们还是在编写程序的时候需要考虑内存管理的问题,例如:

class Stack

{

public Object[] elements;

//原文为private,但这里改为public为了测试下面代码

public int size=0;

 

public Stack(int initialCapacity)

{

this.elements=new Object[initialCapacity];

}

 

public void push(Object e)

{

ensureCapacity();

elements[size++]=e;

}

 

public Object pop() throws Exception

{

if(size==0)

throw new Exception();

return elements[--size];

}

private void ensureCapacity()

{

if(elements.length==size)

{

Object[] oldElements=elements;

elements=new Object[2*elements.length+1];

System.arraycopy(oldElements,0,elements,0,size);

}

}

}

上面的这个程序有一个“内存泄漏”问题,最终会导致程序失败(OutOfMemoryError错误)。如果栈先是增长,然后收缩,那么栈中弹出来的对象将不会被当做垃圾回收,即使使用栈的客户程序不再引用这些对象,它们也不会被垃圾回收。因为栈内部维护着对这些对象的过期引用(即永远也不会再被解除的引用)。在上面的代码中,凡是在elements数组的“活动区域”之外的引用都是过期的,elements的活动区域是指下标小于size的那一部分。

举例来说,我们向栈中push进了10个对象,那么现在size的值为10;当我们弹出一个对象的时候,--size9,也就是Object[9]中引用的对象将被弹出;但是问题出来了,当Object[9]引用的对象被弹出后,该对象所对应的位置的对象不会被回收,例如:

public class stackTest

{

        public static Stack stack=new Stack(20);

        public static void main(String[] args)

        {

            try

                {

                    for (int i=0;i<=9;i++)

                    {

                            String a="Hello "+i;

                            stack.push(a);

                    }

                    String b=new String((String)stack.pop());                   

                    System.out.println(b);

                    System.out.println((String)stack.elements[9]);

                }

                catch(Exception e)

                {

                        e.printStackTrace();

                }

                System.out.println((String)stack.elements[9]);

        }

}

运行程序发现打印三个Hello 9,栈中元素的弹出并没有消除对栈中对象的引用。

对于垃圾回收器来说,它所管理的是elements数组的内存空间,当我们从栈中pop出元素时,对于垃圾回收器来说,element数组依然存在,它不会单独收回elements数组中的一个元素,elememts数组中的对象是由Stack来管理的,不受垃圾回收器的作用。

解决方法:一旦对象引用已经过期,只需清空这些引用即可。pop方法的修订版本如下:

public Object pop() throws Exception

{

if(size==0)

throw new Exception();

Object result=elements[size--];

elements[size]=null;

return result;

}

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值