android/guava/src/com/google/common/base/internal/Finalizer.java
public static void startFinalizer(
      Class<?> finalizableReferenceClass,
      ReferenceQueue<Object> queue,
      PhantomReference<Object> frqReference) {
    /*
     * We use FinalizableReference.class for two things:
     *
     * 1) To invoke FinalizableReference.finalizeReferent()
     *
     * 2) To detect when FinalizableReference's class loader has to be garbage collected, at which
     * point, Finalizer can stop running
     */
    if (!finalizableReferenceClass.getName().equals(FINALIZABLE_REFERENCE)) {
      throw new IllegalArgumentException("Expected " + FINALIZABLE_REFERENCE + ".");
    }

    Finalizer finalizer = new Finalizer(finalizableReferenceClass, queue, frqReference);
    String threadName = Finalizer.class.getName();
    Thread thread = null;
    if (bigThreadConstructor != null) {
      try {
        boolean inheritThreadLocals = false;
        long defaultStackSize = 0;
        thread =
            bigThreadConstructor.newInstance(
                (ThreadGroup) null, finalizer, threadName, defaultStackSize, inheritThreadLocals);
      } catch (Throwable t) {
        logger.log(
            Level.INFO, "Failed to create a thread without inherited thread-local values", t);
      }
    }
    if (thread == null) {
      thread = new Thread((ThreadGroup) null, finalizer, threadName);
    }
    thread.setDaemon(true);

    try {
      if (inheritableThreadLocals != null) {
        inheritableThreadLocals.set(thread, null);
      }
    } catch (Throwable t) {
      logger.log(
          Level.INFO,
          "Failed to clear thread local values inherited by reference finalizer thread.",
          t);
    }

    thread.start();
  }
public static void startFinalizer(
      Class<?> finalizableReferenceClass,
      ReferenceQueue<Object> queue,
      PhantomReference<Object> frqReference) {
    /*
     * We use FinalizableReference.class for two things:
     *
     * 1) To invoke FinalizableReference.finalizeReferent()
     *
     * 2) To detect when FinalizableReference's class loader has to be garbage collected, at which
     * point, Finalizer can stop running
     */
    if (!finalizableReferenceClass.getName().equals(FINALIZABLE_REFERENCE)) {
      throw new IllegalArgumentException("Expected " + FINALIZABLE_REFERENCE + ".");
    }

    Finalizer finalizer = new Finalizer(finalizableReferenceClass, queue, frqReference);
    String threadName = Finalizer.class.getName();
    Thread thread = null;
    if (bigThreadConstructor != null) {
      try {
        boolean inheritThreadLocals = false;
        long defaultStackSize = 0;
        thread =
            bigThreadConstructor.newInstance(
                (ThreadGroup) null, finalizer, threadName, defaultStackSize, inheritThreadLocals);
      } catch (Throwable t) {
        logger.log(
            Level.INFO, "Failed to create a thread without inherited thread-local values", t);
      }
    }
    if (thread == null) {
      thread = new Thread((ThreadGroup) null, finalizer, threadName);
    }
    thread.setDaemon(true);

    try {
      if (inheritableThreadLocals != null) {
        inheritableThreadLocals.set(thread, null);
      }
    } catch (Throwable t) {
      logger.log(
          Level.INFO,
          "Failed to clear thread local values inherited by reference finalizer thread.",
          t);
    }

    thread.start();
  }
Starts the Finalizer thread. FinalizableReferenceQueue calls this method reflectively.

@param finalizableReferenceClass FinalizableReference.class.
@param queue a reference queue that the thread will poll.
@param frqReference a phantom reference to the FinalizableReferenceQueue, which will be queued
either when the FinalizableReferenceQueue is no longer referenced anywhere, or when its
close() method is called.