Module java.base

Package java.lang.ref


package java.lang.ref
提供引用对象类,支持与垃圾收集器的有限交互。程序可以使用引用对象来维护对另一个对象的引用,以便后者仍然可以被收集器回收。程序还可以安排在收集器确定给定对象的可达性已更改后的一段时间内通知自己。

包规范

引用对象 封装对另一个对象的引用,使得引用本身可以像任何其他对象一样被检查和操作。提供了三种类型的引用对象,每种都比上一种更弱: 软引用弱引用虚引用。每种类型对应不同级别的可达性,如下所定义。软引用用于实现内存敏感缓存,弱引用用于实现不会阻止其键(或值)被回收的规范化映射,虚引用用于调度死后清理操作。死后清理操作可以由 Cleaner 注册和管理。

每种引用对象类型由抽象基类 Reference 类的子类实现。这些子类的实例封装了对特定对象的单个引用,称为 引用对象。除了清除操作之外,引用对象在其他方面是不可变的,因此不提供 set 操作。程序可以进一步对这些子类进行子类化,添加其所需的字段和方法,或者可以不加修改地使用这些子类。

通知

程序可以通过在创建引用对象时向 引用队列 注册适当的引用对象来请求在对象的可达性发生变化时收到通知。在垃圾收集器确定引用对象的可达性已更改为与引用类型相对应的值后的一段时间,它将清除引用并将其添加到相关队列中。此时,引用被视为 已入队。程序可以通过轮询或阻塞直到引用变为可用来从队列中移除引用。引用队列由 ReferenceQueue 类实现。

注册引用对象与其队列之间的关系是单向的。也就是说,队列不会跟踪注册到其中的引用。如果注册的引用本身变得不可达,则它将永远不会被入队。使用引用对象的程序有责任确保对象在程序对其引用感兴趣的时间内保持可达性。

虽然一些程序可能选择专门为从一个或多个队列中移除引用对象并处理它们而分配一个线程,但这并非必需。通常效果良好的一种策略是在执行某些其他相对频繁的操作过程中检查引用队列。例如,使用弱引用实现弱键的哈希表可以在每次访问表时轮询其引用队列。这就是 WeakHashMap 类的工作方式。由于 ReferenceQueue.poll 方法仅检查内部数据结构,因此此检查将对哈希表访问方法的开销很小。

可达性

从最强到最弱,不同级别的可达性反映了对象的生命周期。它们的操作定义如下:
  • 如果对象可以被某个线程访问而无需遍历任何引用对象,则对象是 强可达 的。新创建的对象由创建它的线程强可达。
  • 如果对象不是强可达但可以通过遍历软引用而达到,则对象是 软可达 的。
  • 如果对象既不是强可达也不是软可达,但可以通过遍历弱引用而达到,则对象是 弱可达 的。当对弱可达对象的弱引用被清除时,对象变得可终结。
  • 如果对象既不是强可达、软可达、也不是弱可达,它已经被终结,并且某个虚引用引用它,则对象是 虚可达 的。
  • 最后,如果对象在任何以上方式中都不可达,因此可以被回收,则对象是 不可达 的。
自版本:
1.2
  • Class
    Description
    Cleaner 管理一组对象引用和相应的清理操作。
    Cleanable 表示在 Cleaner 中注册的对象和清理操作。
    虚引用对象,在收集器确定其引用对象可能被回收后入队。
    引用对象的抽象基类。
    引用队列,垃圾收集器在检测到适当的可达性更改后将注册的引用对象附加到其中。
    软引用对象,根据内存需求,由垃圾收集器自行清除。
    弱引用对象,不会阻止其引用对象被设为可终结、终结,然后被回收。