了解java.lang.ref.Reference

本文主要讲述java.lang.ref.Reference这个类的一些基本概念和使用方法

Reference

// 判断次Reference是否已被回收
public boolean isEnqueued()
// 手动进行回收
public boolean enqueue() 
// 去掉对value的引用
public void clear()

java.lang.ref 包中提供了三种主要类型的引用对象:

  1. SoftReference
    软引用在内存不足时才会被垃圾收集器清除。在内存充足时,软引用指向的对象不会被回收。
    用途:适用于实现内存敏感的缓存。

  2. WeakReference:弱引用不会阻止其引用的对象被垃圾收集。
    常用于实现映射(如 WeakHashMap),不希望引用的对象阻止其被回收。
    一旦没有强引用指向该对象,垃圾收集器会立即回收该对象。

  3. PhantomReference:虚引用在对象被回收后会被加入到引用队列中,且无法通过 get() 方法访问。
    用于管理资源的清理操作。
    与软引用和弱引用不同,虚引用不能直接访问其引用的对象。

  4. java.lang.ref.FinalReference

当引用的对象被回收时,通过get方法获取到的值就为null,同时还提供了enqueue方法可以手动将引用的值置为null

ReferenceQueue

java.lang.ref.ReferenceQueue

概念:引用队列可以用来监控引用对象的状态。
使用:在创建引用对象时,可以将其注册到一个引用队列中;当其引用的对象被回收时,该引用对象会被加入到引用队列中。
方法:
poll(): 检查队列中是否有可用的引用对象。
remove(): 阻塞直到队列中有引用对象可以移除。

Reference Handler线程

Reference加载时会启动一个名为Reference Handler的后台线程,负责处理与引用对象(如软引用、弱引用和虚引用)相关的任务。
它主要干两件事情

  1. 处理引用队列:Reference Handler 线程主要负责监控和处理注册到引用队列中的引用对象。
  2. 清理操作:当某个对象被垃圾收集器回收时,相关的引用对象会被加入到引用队列中,Reference Handler 线程会处理这些引用并执行相应的清理操作。
static {
    ThreadGroup tg = Thread.currentThread().getThreadGroup();
    for (ThreadGroup tgn = tg;
          tgn != null;
          tg = tgn, tgn = tg.getParent());
    Thread handler = new ReferenceHandler(tg, "Reference Handler");
    /* If there were a special system-only priority greater than
      * MAX_PRIORITY, it would be used here
      */
    handler.setPriority(Thread.MAX_PRIORITY);
    handler.setDaemon(true);
    handler.start();

    // provide access in SharedSecrets
    SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
        @Override
        public boolean tryHandlePendingReference() {
            return tryHandlePending(false);
        }
    });
}

如下图所示:
alt text

引用队列:每个引用对象(如 SoftReference、WeakReference 和 PhantomReference)在创建时可以指定一个引用队列。当这些引用对象的 referent 被回收时,它们会被加入到这个引用队列中。
持续监控:Reference Handler 线程会持续运行,调用 ReferenceQueue 的 remove() 方法,等待引用对象的到来。
执行清理:一旦引用对象被加入到队列,Reference Handler 线程可以读取这些引用并执行相应的清理逻辑,比如释放资源或通知其它组件。

WeakHashMap

https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/WeakHashMap.html

Map.Entry会持续存留在HashMap中

LRU缓存, 例如LinkedHashMap

import java.util.LinkedHashMap;
import java.util.Map;

public class LRUCache<K, V> extends LinkedHashMap<K, V> {

    private final int maxSize;

    public LRUCache(int maxSize) {
        super(maxSize, 0.75F, true);
        this.maxSize = maxSize;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > maxSize;
    }
}

参考资料

  1. https://stackoverflow.com/questions/68425363/understanding-weakreferences
posted @ 2025-07-27 23:38  vonlinee  阅读(15)  评论(0)    收藏  举报