一、前言
在java中,对象的引用被划分为四种级别,这四种级别由高到低依次为:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)4种。
强引用(Strong Reference)
强引用在java中是最常见的,把一个对象赋值给一个引用变量,这个引用变量就是一个强引用。如果一个对象被强引用变量引用着,那么这个对象处于可达状态,是不会被垃圾回收机制回收的。
Object obj = new Object();
即使是内存不足,java虚拟机宁愿抛出OutOfMemoryError,使程序终止,也不会回收具有强引用的对象来解决内存不足的问题。
我们来分析一个代码:
public static void main(String[] args) {
Object obj = new Object();
}
main方法运行,main方法对应的栈帧入栈,obj为对象的引用变量,存放在栈帧里面,真正的对象(new Object())是存放在堆里面的,main方法运行结束,对应的栈帧就会出栈,则这个栈帧里面的引用就会随之销毁,则引用对象的引用数量就会归0,那么这个对象就会被回收。
我们可以显示地将对象置空(null),那么垃圾收集器就会认为该对象不存在引用,这时就可以回收该对象。
obj = null;
软引用(Soft Reference)
软引用需要用SoftReference类来实现,对于只有软引用的对象来说,当系统内存足够时它不会被回收,当系统内存空间不足时它会被回收。以下为代码示例:
String str = new String("hello world");
SoftReference<String> softReference = new SoftReference<>(str);
软引用通常用在对内存敏感的程序中,比如高速缓存。
弱引用(Weak Reference)
弱引用需要用WeakReference类来实现,它比软引用的生存周期更短,对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管JVM的内存空间是否足够,都会回收该对象占用的内存。以下为代码示例:
String str = new String("hello world");
WeakReference<String> weakReference = new WeakReference<>(str);
虚引用(PhantomReference)
虚引用需要使用PhantomReference类来实现,不能单独使用,需要和引用队列来联合使用。虚引用的主要作用是跟踪对象被垃圾回收的状态。
虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
String str = new String("hello world");
//创建引用队列
ReferenceQueue<Object> queue = new ReferenceQueue<>();
//创建虚引用,需要跟一个引用队列来关联
PhantomReference pr = new PhantomReference(str, queue);
下面我们来用一张图进行总结:
| 引用类型 | 被垃圾回收时间 | 用途 | 生存时间 |
|---|---|---|---|
| 强引用 | 从来不会 | 对象的一般状态 | JVM停止运行时终止 |
| 软引用 | 当内存不足时 | 对象缓存 | 内存不足时终止 |
| 用 | 正常垃圾回收时 | 对象缓存 | 垃圾回收后终止 |
| 虚引用 | 正常垃圾回收时 | 跟踪对象的垃圾回收 | 垃圾回收后终止 |