Java 的4种引用类型

110 阅读3分钟

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 排版