Java 的4种引用
强引用 - 软引用 - 弱引用 - 虚引用
1. 强引用
默认的引用类型就是强引用,比如
Object obj = new Object()
如果强引用的对象正在被引用着,这个对象就永远不会被垃圾回收(即使内存溢出也不会被回收)
2. 软引用 SoftReference
// 创建一个字节数组
byte[] b = new byte[1024];
// 创建软引用
SoftReference<byte[]> reference = new SoftReference<>(b);
当对象是软引用的时候,只有在虚拟机执行垃圾回收后,内存还不足的情况下,软引用将会被回收。
3. 弱引用 WeakReference
// 创建对象
Object object = new Object();
// 创建弱引用
WeakReference<Object> reference = new WeakReference<>(object);
// **获取引用对象:** 通过**get()**方法可以获取弱引用所引用的对象。但请注意,由于弱引用的对象可能在任何时候被回收,所以在使用之前最好先判断是否为**null**。
Object obj = reference.get();
if (obj != null) {
// 使用 obj
}
WeakReference 对象不会阻止它引用的对象被垃圾回收。当垃圾回收器每次运行时并发现一个对象只被弱引用引用时,它会回收这个对象。当对象只有弱引用时,会在下次垃圾回收时被回收。
弱引用的使用场景:
- 缓存管理: 弱引用可以用于实现缓存,当内存不足时,垃圾回收器可以自动回收缓存对象。
- 监听器管理: 在事件监听中,可以使用弱引用来管理监听器,避免因监听器而导致对象无法回收。
- 对象关联性: 当需要关联对象但又不希望阻止它们被垃圾回收时,可以使用弱引用。
- 内存敏感操作: 在需要进行内存敏感操作(如图像处理)时,可以使用弱引用避免因为内存不足而导致程序崩溃。
注意事项:
- 弱引用的对象可能会在任何时候被垃圾回收,因此在使用时需要小心处理可能为**
null**的情况。 - 需要确保弱引用对象本身不会被提前回收,可以在适当的作用域内保持一个强引用。
4. 虚引用
在这个例子中,phantomReference.get() 总是返回 null。如果垃圾回收器回收了 new String("PhantomReference Example") ,phantomReference 将被加入到 referenceQueue 中。
// 创建一个字节数组
byte[] b = new byte[1024];
// 创建引用队列
ReferenceQueue<byte[]> queue = new ReferenceQueue<>(b);
// 创建虚引用
PhantomReference<byte> phantomReference = new PhantomReference<>(b, queue);
// 获取不到引用对象:调用 PhantomReference.get() 总是返回 null。
System.out.println("Before GC: " + phantomReference.get()); // Always null
// Trigger garbage collection
b = null; // Remove the strong reference
System.gc();
// Wait for a short while to ensure GC has occurred
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (queue.poll() != null) {
System.out.println("After GC: Phantom reference enqueued");
} else {
System.out.println("After GC: Phantom reference not enqueued");
}
特点
- 对象已经被回收:
PhantomReference对象仅在它所引用的对象已经被回收并且所有PhantomReference已被清除之前被添加到引用队列(ReferenceQueue)。 - 获取不到引用对象:调用
PhantomReference.get()总是返回null。 - 主要用途:跟踪对象被垃圾回收后的清理工作,比如资源释放。
虚引用的使用场景:
- 清理工作:
PhantomReference主要用于在对象被回收后执行一些清理工作,类似于finalize机制,但更灵活和可控。 - 直接内存管理:虚引用常常用于管理直接内存(如 Netty 中的
ByteBuffer)。通过虚引用,可以在对象被垃圾回收后执行特定的内存释放操作,避免内存泄漏。
综上所述,在对象被回收后,虚引用会被加入到引用队列中。get() 方法总是返回 null。主要用于管理对象被回收后的清理工作,类似于 finalize 机制,但更灵活和可控。虚引用只是起一个通知的作用。
本文使用 markdown.com.cn 排版