读书人

java里的弱引述

发布时间: 2012-12-28 10:29:05 作者: rapoo

java里的弱引用
真是惭愧啊,搞了好几年Java,居然才知道Java里的弱引用!
"Java拥有垃圾回收机制,我们不需要手工释放对象",在讲到java的垃圾回收时,老师们总是这样一句带过。似乎Java真的很智能(实际上确实很智能),但是有时候她的垃圾回收机制并不能很好的理解我们的意图,考虑这么一种情况:

有一个Swing面板JPanel中有一个成员变量obj,窗体加载这个JPanel的时候,将obj加入一个全局map(static类的static属性)中,如果JPanel被卸载了,obj会被回收吗?
?
我们肯定希望obj会被回收,因为JPanel已经被卸载了,作为成员变量的obj也就没有存在的意义了。
?
但是,实际上,这个obj不会被回收,因为它还被那个全局的map引用!这还不是最糟糕的,万一这个obj还引用其它对象,这些对象也一律不会被回收,这就造成了很大的内存浪费。幸运的是,java提供了WeakReference解决这个问题。看下面的代码:

public class Test {    public static Map map=new HashMap();    public static void main(String[] args){        MyObject obj=new MyObject("obj1");        map.put("obj1",obj);        test();    }    static void test(){        Thread t=new Thread(new Runnable() {            @Override            public void run() {                int i=0;                while (true){                    System.out.println(i++);                    System.gc();                    try {                        Thread.sleep(1000);                    } catch (Exception e) {                        e.printStackTrace();                    }                }            }        });        t.start();    }}class MyObject{    String id;    public MyObject(String id){        this.id=id;    }    @Override    public void finalize() {        System.out.println(id + " is finalized");    }}

将MyObject类的一个实例(obj)放入一个全局map,程序跳入test方法后,每隔1s调用垃圾回收器,虽然此时已经超出了obj的作用域,但是因为map还引用着obj,所以它不会被回收。

修改一下代码,将map.put("obj1",obj)改为map.put("obj1",new WeakReference(obj)),再运行程序,可以发现控制台很快输出"obj1 is finalized",说明对象被回收了。

有人可能疑惑,存入map的是WeakReference,要用obj怎么办?WeakReference提供了一个get方法,可以返回包装的对象,如果返回null,说明对象已经被回收了。

Java还提供了SoftReference(软引用),当内存紧张时,它所包装的对象可能被回收,API里说用它来做缓存不错,大家可以自行研究。

读书人网 >编程

热点推荐