Random Tech Thoughts

The title above is not random

Weak Reference

看到了这篇 blog 文章,Understanding Weak Reference。作者说很多 Java 程序员都不知道什么是 weak reference,他的评论至少对我来说是对的。不过这也证明了 Java 的一点好处就是即使你不是很懂 Java 也能用 Java 写程序,不过写的比较烂而已。有人说 Java 程序通常都是一团糟,其实是因为用 Java 写程序的人有许多都不能算合格的 Java 程序员,从这一点上来说这又是 Java 的缺点。扯远了,总之,我觉得我的 Java 不合格,学 Java 还从来没有完整看过哪怕一本书,或许看过了的话就不会连这个在 Java 里有了近一个年代的东西都完全不知道……

回到正题上来。Weak Reference 是什么?其实是跟垃圾收集相关的东西。我做个原文摘要,有兴趣的看原文吧。

有 Weak Reference 当然也有 Strong Reference。其实我们常用的引用就是 strong reference,比如下面代码就会创建一个 strong reference。

Object foo = new Object();

执行上面代码的时候将创建一个对象,变量 foo 中存放了这个对象的 Strong Reference,利用它可以访问到该对象。

记住一点,只要有 Strong Reference 指向对象,这个对象就不会被垃圾收集器回收。Weak Reference 同样用来引用对象,但是 Weak Reference 指向的对象是可能被回收的,比如当没有 Strong Reference 指向它的时候。

那么什么时候可能用到 Weak Reference?看看下面几个场景。

  1. 你想给对象附加一些信息,于是你用一个 Hashtable 把对象和附加信息关联起来。你不停的把对象和附加信息放入 Hashtable 中,但是当对象用完的时候,你不得不把对象再从 Hashtable 中移除,否则它占用的内存变不会释放。万一你忘记了,那么没有从 Hashtable 中移除的对象也可以算作是内存泄漏。理想的状况应该是当对象用完时,Hashtable 中的对象会自动被垃圾收集器回收,不然你就是在做垃圾回收的工作了。
  2. 你想实现一个图片缓存,因为加载图片的开销比较大。你将图片对象的引用放入这个缓存,以便以后能够重新使用这个对象。但是你必须决定缓存中的哪些图片不再需要了,从而将引用从缓存中移除。不管你使用什么管理缓存的算法,你实际上都在处理垃圾收集的工作,更简单的办法(除非你有特殊的需求,这也应该是最好的办法)是让垃圾收集器来处理,由它来决定回收哪个对象。

Weak Reference 这时候就能派上用场了。把对象的 weak reference 放入 Hashtable 或者缓存中,当没有 strong reference 指向他们的时候,对象就可以被垃圾收集器回收了。实际上,有一个 WeakHashMap 就是专门做这个事的。 那么怎样创建对象的 weak reference 呢?很简单,Java 标准库中有个类 WeakReference,

WeakReference weakref = new WeakReference(ref);

这样 weakref 就是 ref 指向对象的一个 weak reference。要引用这个 weak reference 指向的对象可以用 get 方法。

Object ref = weakref.get();

注意,get 可能返回 null,这时原先指向的对象就不可用了,它可能已经被回收了。

除了 Weak Reference 以外还有 Soft Reference, Phantom references。更多内容除了参考那篇 blog 原文,也可以参考 JDK 文档的 java.lang.ref 包和相关类的文档。我对对象什么情况下可用被回收的解释可能不是完全正确,那个 WeakReference 的文档的解释实在是……如发现错误请纠正。

Comments