虚引用的使用场景有哪些?

Jacob-Chen / 2024-08-22 / 原文

虚引用的一些主要使用场景和特点:

  1. 跟踪对象被垃圾回收的状态
  2. 管理堆外内存
  3. 调试和分析

跟踪对象被垃圾回收的状态

虚引用的主要用途是跟踪对象何时被垃圾回收。当一个对象仅被虚引用引用时,在下一次垃圾回收时,这个对象会被回收,而虚引用会被加入到其关联的引用队列中。

ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> reference = new PhantomReference<>(new Object(), queue);

// 等待对象被回收
Reference<?> polledRef = queue.poll();
if (polledRef != null) {
    System.out.println("Object has been collected.");
}

管理堆外内存

虚引用常用于管理堆外内存(Direct Memory)。例如,在NIO中的DirectByteBuffer使用虚引用来管理堆外内存的释放。

public class DirectMemoryManager {
    private static final ReferenceQueue<Object> QUEUE = new ReferenceQueue<>();

    static class DirectMemoryReference extends PhantomReference<Object> {
        private final long address;

        DirectMemoryReference(Object referent, long address) {
            super(referent, QUEUE);
            this.address = address;
        }

        void cleanUp() {
            // 释放堆外内存
            unsafe.freeMemory(address);
        }
    }

    public static void allocateMemory(Object owner, long size) {
        long address = unsafe.allocateMemory(size);
        new DirectMemoryReference(owner, address);
    }

    public static void processQueue() {
        DirectMemoryReference ref;
        while ((ref = (DirectMemoryReference)QUEUE.poll()) != null) {
            ref.cleanUp();
            ref.clear();
        }
    }
}

调试和分析

虚引用可以用于调试内存泄漏或分析对象生命周期,因为它们允许你在不影响对象正常垃圾回收的情况下跟踪对象。