Module java.base
Package java.lang.ref

Class Cleaner

java.lang.Object
java.lang.ref.Cleaner

public final class Cleaner extends Object
清理器 管理一组对象引用和相应的清理操作。

清理操作被 注册 在清理器被通知对象已经变为虚引用可达后运行。清理器使用 PhantomReferenceReferenceQueue 来在 可达性 发生变化时被通知。

每个清理器独立运行,管理待处理的清理操作并处理线程和终止,当清理器不再使用时。注册对象引用和相应的清理操作会返回一个 Cleanable。最有效的使用方式是在对象关闭或不再需要时显式调用 clean 方法。清理操作是一个 Runnable,在对象变为虚引用可达后最多被调用一次,除非已经被显式清理。请注意,清理操作不能引用被注册的对象。如果引用了,对象将不会变为虚引用可达,清理操作也不会自动被调用。

清理操作的执行由与清理器关联的线程执行。清理操作抛出的所有异常都会被忽略。清理器和其他清理操作不受清理操作中的异常影响。线程运行直到所有注册的清理操作完成并且清理器本身被垃圾回收器回收。

System.exit 期间清理器的行为是特定于实现的。不保证清理操作是否被调用。

除非另有说明,在此类的构造函数或方法中传递 null 参数将导致抛出 NullPointerException

API 注意:
清理操作仅在关联对象变为虚引用可达后才被调用,因此很重要的是实现清理操作的对象不持有对该对象的引用。在此示例中,一个静态类封装了清理状态和操作。不应使用“内部”类(匿名或非匿名),因为它隐含地包含对外部实例的引用,从而阻止其变为虚引用可达。选择新的清理器或共享现有清理器取决于用例。

如果 CleaningExample 在 try-finally 块中使用,则 close 方法调用清理操作。如果未调用 close 方法,则在 CleaningExample 实例变为虚引用可达时,清理器将调用清理操作。


 public class CleaningExample implements AutoCloseable {
        // 一个清理器(最好在库中共享一个,但为了示例起见,这里创建一个新的)
        private static final Cleaner cleaner = Cleaner.create();

        // State 类捕获清理所需的信息。
        // 它不得持有对正在清理的实例的引用
        // 因此在此示例中它是一个静态内部类。
        static class State implements Runnable {

            State(...) {
                // 初始化清理操作所需的 State
            }

            public void run() {
                // 访问 State 的清理操作,最多执行一次
            }
        }

        private final State state;
        private final Cleaner.Cleanable cleanable;

        public CleaningExample() {
            this.state = new State(...);
            this.cleanable = cleaner.register(this, state);
        }

        public void close() {
            cleanable.clean();
        }
    }
 
清理操作可以是一个 lambda,但很容易捕获对象引用,通过引用正在清理的对象的字段,从而阻止对象变为虚引用可达。如上所述,使用静态嵌套类将避免意外保留对象引用。

清理操作应准备好与其他清理操作并发调用。通常,清理操作应该非常快速执行,不应该阻塞。如果清理操作阻塞,可能会延迟处理注册到同一清理器的其他清理操作。所有注册到清理器的清理操作应该是相互兼容的。

自 JDK 版本:
9
  • Method Details

    • create

      public static Cleaner create()
      返回一个新的 Cleaner

      清理器创建一个 守护线程 来处理虚引用可达的对象并调用清理操作。线程的 上下文类加载器 设置为 系统类加载器。线程没有权限,只有在设置了 SecurityManager 时才会执行。

      清理器在自身变为虚引用可达且所有注册的清理操作完成时终止。

      返回:
      一个新的 Cleaner
      抛出:
      SecurityException - 如果当前线程不允许创建或启动线程。
    • create

      public static Cleaner create(ThreadFactory threadFactory)
      返回一个使用 ThreadFactory 中的 Thread 的新 Cleaner

      从线程工厂的 newThread 方法中获取的线程被设置为 守护线程 并启动以处理虚引用可达的对象并调用清理操作。每次调用时,线程工厂 必须提供适合执行清理操作的 Thread。

      清理器在自身变为虚引用可达且所有注册的清理操作完成时终止。

      参数:
      threadFactory - 用于返回处理清理操作的新 ThreadThreadFactory
      返回:
      一个新的 Cleaner
      抛出:
      IllegalThreadStateException - 如果线程工厂中的线程 不是新线程
      SecurityException - 如果当前线程不允许创建或启动线程。
    • register

      public Cleaner.Cleanable register(Object obj, Runnable action)
      注册一个对象和一个清理操作,当对象变为虚引用可达时运行。请参考上面的 API 注意,了解有关清理操作行为的注意事项。
      参数:
      obj - 要监视的对象
      action - 当对象变为虚引用可达时要调用的 Runnable
      返回:
      一个 Cleanable 实例