在Java中,除了基本类型之外,其他类型都是通过指向某个对象的对象引用,根据其生命周期的长短分为四类:
强引用
目前最常见的引用,当有引用指向对象时候,垃圾回收器将不会对其进行回收,只有当对象不可达或者显示设置为空时,才会将其回收。在这种引用的情况下,jvm宁愿报出OOM也不会对对象进行回收。
//强引用
Person p = new Person();
补:不可达意指超出引用的作用域。
软引用
软引用实现类:SoftReference
软引用是相对强引用较为弱化的一种引用,弱引用的对象可以具有一定的回收豁免权,只有在当JVM内存不足时候才会去尝试回收这些对象,也就是在抛出oom之前清理软引用对象。适合用来存储有用,但不是必须的对象。例如图片缓存,当还有内存空间的时候可以尽量保存数据,当内存不足时回收数据,可以保留缓存使用同时不会让缓存过大导致内存溢出。
//软引用
SoftReference<PoolFilterable> pool = new SoftReference<PoolFilterable>(img);
具体例子可以查看com.sun.scenario.effect.impl.ImagePool的用法
弱引用
弱引用实现类:WeakReference
弱引用对象,不会阻止它们的引用对象被终结、终结和回收。当发生垃圾回收时,无论内存是否充足,都会回收弱引用对象,弱引用最常用于实现规范化映射。
class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
}
从上面例子可以看到,ThreadLocalMap中的key值就是使用的弱引用对象,其原因在于:threadLocalMap对象被thread持有,如果是强引用的话,只有当thread结束时才能被回收,而弱引用则可以在使用完后立即回收,不必等待thread结束。
幻象引用
幻象引用实现类:PhantomReference
也叫虚引用,从代码中可以看出,对象无法通过虚引用访问对象的任何属性或函数。
//PhantomReference的get方法
public T get() {
return null;
}
幻象引用仅仅是提供了一种确保对象被 finalize 以后,做某些事情的机制。
引用队列
实现类:ReferenceQueue
创建引用时候并将引用关联到相应对象时候可以选择关联相应的引用队列,jvm会在特定时候(GC前)将引用添加进队列里面,我们可以再去队列里面获取相应数据做后续处理。
软引用,弱引用,幻象引用的实现类中都存在传入引用队列的构造方法。新创建引用队列,在软引用,弱引用,虚引用关联引用的时候将队列传入,通过remove方法去引用队列里取被回收的对象,remove是阻塞的操作,代码也很简单,可以自己去翻一下,会一直等到取到对象为止。取到之后可对对象进行回收追踪等操作。