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即可。