最近看下Guice源码,
public void init(FilterConfig filterConfig) throws ServletException {
final ServletContext servletContext = filterConfig.getServletContext();
// Store servlet context in a weakreference, for injection
GuiceFilter.servletContext = new WeakReference<ServletContext>(servletContext);
// In the default pipeline, this is a noop. However, if replaced
// by a managed pipeline, a lazy init will be triggered the first time
// dispatch occurs.
GuiceFilter.pipeline.initPipeline(servletContext);
}
中有WeakReference,经google,记录下:
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?看看下面几个场景。
你想给对象附加一些信息,于是你用一个 Hashtable 把对象和附加信息关联起来。你不停的把对象和附加信息放入 Hashtable 中,但是当对象用完的时候,你不得不把对象再从 Hashtable 中移除,否则它占用的内存变不会释放。万一你忘记了,那么没有从 Hashtable 中移除的对象也可以算作是内存泄漏。理想的状况应该是当对象用完时,Hashtable 中的对象会自动被垃圾收集器回收,不然你就是在做垃圾回收的工作了。
你想实现一个图片缓存,因为加载图片的开销比较大。你将图片对象的引用放入这个缓存,以便以后能够重新使用这个对象。但是你必须决定缓存中的哪些图片不再需要了,从而将引用从缓存中移除。不管你使用什么管理缓存的算法,你实际上都在处理垃圾收集的工作,更简单的办法(除非你有特殊的需求,这也应该是最好的办法)是让垃圾收集器来处理,由它来决定回收哪个对象。
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,这时原先指向的对象就不可用了,它可能已经被回收了。