四种引用类型
1. 强引用
强引用就是最普通的引用方式。
GC 时,只要堆中的对象实例存在强引用与之关联,则绝不会被垃圾回收。
Object o = new Object();
方法中的局部变量的强引用会在方法退出栈帧后自动销毁引用。
对于类的全局变量,消除强引用的方法是对强引用赋值为 null
。这样可以帮助强引用全局变量的垃圾回收。
- 全局变量:类变量
static
, 类实例变量
o = null;
2. 软引用 SoftReference
软引用的对象会在内存不足时被 GC 回收。
- 当没被回收时,软可达对象可以像强引用一样被程序正常访问和使用
SoftReference.get()
会返回对象实例的强引用- 但若对象实例被 GC 回收后,将返回
null
- 但若对象实例被 GC 回收后,将返回
若对象实例与 GC Roots 之间不存在强引用,只存在软引用,则该对象状态为 软可达 状态。
String str = new String("abc"); // 强引用
SoftReference<String> softRef=new SoftReference<String>(str); // 软引用
str = null; // 消除强引用,该 String 实例变为软可达状态
str = softRef.get(); // 重新关联强引用
3. 弱引用 WeakReference
GC 进行垃圾回收时,无论堆内存是否充足,都会回收弱引用对象。
若对象实例与 GC Roots 之间只存在弱引用,则称为 弱可达 状态。
String str = new String("abc");
WeakReference<String> abcWeakRef = new WeakReference<String>(str);
str = null;
软引用 与 弱引用
- 如果缓存的对象较大,使用频率较高,使用软引用较好
- 如果缓存的对象较小,视频频率较低,使用弱引用较好
4. 虚引用 PhantomReference
虚引用作用在于跟踪垃圾回收过程,在对象被收集器回收时收到一个系统通知。 当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在垃圾回收后,将这个虚引用加入引用队列,在其关联的虚引用出队前,不会彻底销毁该对象。
- 可以通过检查引用队列中是否有相应的虚引用来得知对象被 GC 的时机,来进行销毁前的一些操作,比如说资源释放等。
如果一个对象没有强引用和软引用,对于垃圾回收器而言便是可以被清除的,在清除之前,会调用其 finalize()
方法,如果一个对象已经被调用过 finalize()
方法但是还没有被释放,它就变成了一个虚可达对象。
finalize()
方法是Object
类的方法,现在已经不建议被使用。
事实上,虚引用有一个很重要的用途就是用来做堆外内存的释放,DirectByteBuffer
就是通过虚引用来实现堆外内存的释放的。