WeakReference 和 StrongReference

转自:WeakReference 和 StrongReference



StrongReference

1
String abc = new String("abcdf");


这就是创建了一个String的实例然后在变量abc中保存一个强引用,为什么说它强呢?


这是跟垃圾回收器相关的,如果一个对象是通过强引用链(Chain of Strong Reference) 访问到的,也就是像上面那样,那么这个对象是不会被垃圾回收器回收的, 这在正常情况下是正确的,因为你不想垃圾回收器回收你正在使用的对象。


当内存空间不足时,Java虚拟机宁愿抛出OutOfMemory错误,是程序异常终止,也不会为了解决内存不足而回收这类引用的对象。


这就是使用强引用的一个问题, 强引用的另外一个常见的问题就是缓存, 特别是对于那些非常大的数据结构,像图片等等,平差情况下我们是希望程序能缓存这些大的数据结构的,因为重新加载非常耗费服务器资源。


因为缓存就是为了避免重新加载这些大的数据结构的,所以缓存中会保存一个指向内存中数据结构的引用,而这些引用通常都是强引用,所以这些引用会强迫这些大的数据结构保存在内存中,除非用通过某些方法户知道哪一个数据结构不再需要保存在内存中了,然后再把他从缓存中清除。


WeakReference


弱引用就是不保证不被垃圾回收器回收的对象,它拥有比较短暂的生命周期,在垃圾回收器扫描它所管辖的内存区域过程中,一旦发现了只具有弱引用的对象,就会回收它的内存,不过一般情况下,垃圾回收器的线程优先级很低,也就不会很快发现那些只有弱引用的对象。


以下是一个创建弱引用对象的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * WeakReference<br>
 * 顾名思义, 是一个弱引用, 当所引用的对象在 JVM 内不再有强引用时, GC后,弱引用被置成null,并回收所指的对象
 *
 * @throws InterruptedException
 */
public void weakReference() throws InterruptedException {
    WeakReference<Object> wf = new WeakReference<Object>(new String("weakReference"));
    System.out.println("before gc, wf : "   wf.get());
    System.gc();
    Thread.sleep(5000);
    /**
     * weak reference 在 GC 后会被置成null,对象就可以被回收了
     */
    System.out.println("after gc, wf : "   wf.get());
}


输出结果:

1
2
before gc, wf : weakReference
after gc, wf : null


另一个Demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static class Entry extends WeakReference<Object> {
    public Entry(Object v) {
        super(v);
    }
}
public static void main(String[] args) {
    try {
        Thread t = Thread.currentThread();
        Entry e = new Entry(t.toString());
        System.out.println("before gc, t : "   e.get());
        System.gc();
        Thread.sleep(5000);
        System.out.println("before gc, t : "   e.get());
    } catch (Exception e) {
        e.printStackTrace();
    }
}


输出结果:

1
2
before gc, t : Thread[main,5,main]
before gc, t : null


转载请并标注: “本文转载自 linkedkeeper.com (文/张松然)”