java的弱引用、软引用和虚引用
Java中的弱引用、软引用和虚引用是用于解决内存泄漏问题的引用类型。它们具有不同的特性,可以在不同场景下使用。
1. *弱引用(WeakReference)
弱引用用于引用对象,但不影响对象的垃圾回收。当系统内存空间不足时,JVM会优先回收被弱引用引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,当被引用的对象被垃圾回收时,就会将弱引用对象加入到引用队列中。
示例代码:
import java.lang.ref.WeakReference;
import java.lang.ref.ReferenceQueue;
public class WeakReferenceExample {
public static void main(String[] args) {
String str = new String("Hello");
ReferenceQueue<String> queue = new ReferenceQueue<>();
WeakReference<String> weakRef = new WeakReference<>(str, queue);
str = null; // 显式将强引用设置为null,使对象成为垃圾
System.gc(); // 显式调用垃圾回收器
try {
// 如果弱引用对象被加入引用队列,说明被引用的对象已经被回收
if (queue.remove(1000) != null) {
System.out.println("The object has been garbage collected.");
} else {
System.out.println("The object is still alive.");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2. 软引用(SoftReference)
软引用用于引用对象,只有当系统内存不足时,才会回收被软引用引用的对象。软引用同样可以和一个引用队列联合使用。软引用常用于实现内存敏感的缓存。
示例代码:
import java.lang.ref.SoftReference;
import java.lang.ref.ReferenceQueue;
public class SoftReferenceExample {
static class HeavyObject {
private byte[] spaceHolder = new byte[1024 * 10]; // 占用一定的内存空间
}
public static void main(String[] args) {
HeavyObject heavyObj = new HeavyObject();
ReferenceQueue<HeavyObject> queue = new ReferenceQueue<>();
SoftReference<HeavyObject> softRef = new SoftReference<>(heavyObj, queue);
heavyObj = null; // 显式将强引用设置为null,使对象成为垃圾
// 在内存充足的情况下,对象不会被回收
System.out.println("Is the object alive? " + (softRef.get() != null));
// 模拟内存不足的情况,触发垃圾回收
byte[] memoryFiller = new byte[1024 * 1024 * 100]; // 分配大量内存空间
System.out.println("Is the object alive? " + (softRef.get() != null)); // 对象可能被回收了
}
}
3. 虚引用(PhantomReference)
虚引用是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来获取一个对象实例。唯一的用处就是能在这个对象被收集器回收时收到一个系统通知。虚引用必须和引用队列联合使用,其主要作用是跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用,如果虚引用所引用的对象被垃圾回收,就会将虚引用加入到引用队列中,而不会像软引用和弱引用那样直接置为null。
由于虚引用不会影响对象的生存时间,也不能通过虚引用来获取对象实例,因此其示例代码与弱引用和软引用的示例代码类似,只是将WeakReference
或SoftReference
替换为PhantomReference
即可。