1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.ref;
  27 
  28 import java.util.Objects;
  29 import java.util.concurrent.ThreadFactory;
  30 
  31 import jdk.internal.ref.CleanerImpl;
  32 
  33 /**
  34  * {@code Cleaner} manages a set of object references and corresponding cleaning actions.
  35  * <p>
  36  * Cleaning actions are {@link #register(Object object, Runnable action) registered}
  37  * to run after the cleaner is notified that the object has become
  38  * phantom reachable.
  39  * The cleaner uses {@link PhantomReference} and {@link ReferenceQueue} to be
  40  * notified when the <a href="package-summary.html#reachability">reachability</a>
  41  * changes.
  42  * <p>
  43  * Each cleaner operates independently, managing the pending cleaning actions
  44  * and handling threading and termination when the cleaner is no longer in use.
  45  * Registering an object reference and corresponding cleaning action returns
  46  * a {@link Cleanable Cleanable}. The most efficient use is to explicitly invoke
  47  * the {@link Cleanable#clean clean} method when the object is closed or
  48  * no longer needed.
  49  * The cleaning action is a {@link Runnable} to be invoked at most once when
  50  * the object has become phantom reachable unless it has already been explicitly cleaned.
  51  * Note that the cleaning action must not refer to the object being registered.
  52  * If so, the object will not become phantom reachable and the cleaning action
  53  * will not be invoked automatically.
  54  * <p>
  55  * The execution of the cleaning action is performed
  56  * by a thread associated with the cleaner.
  57  * All exceptions thrown by the cleaning action are ignored.
  58  * The cleaner and other cleaning actions are not affected by
  59  * exceptions in a cleaning action.
  60  * The thread runs until all registered cleaning actions have
  61  * completed and the cleaner itself is reclaimed by the garbage collector.
  62  * <p>
  63  * The behavior of cleaners during {@link System#exit(int) System.exit}
  64  * is implementation specific. No guarantees are made relating
  65  * to whether cleaning actions are invoked or not.
  66  * <p>
  67  * Unless otherwise noted, passing a {@code null} argument to a constructor or
  68  * method in this class will cause a
  69  * {@link java.lang.NullPointerException NullPointerException} to be thrown.
  70  *
  71  * @apiNote
  72  * The cleaning action is invoked only after the associated object becomes
  73  * phantom reachable, so it is important that the object implementing the
  74  * cleaning action does not hold references to the object.
  75  * In this example, a static class encapsulates the cleaning state and action.
  76  * An "inner" class, anonymous or not,  must not be used because it implicitly
  77  * contains a reference to the outer instance, preventing it from becoming
  78  * phantom reachable.
  79  * The choice of a new cleaner or sharing an existing cleaner is determined
  80  * by the use case.
  81  * <p>
  82  * If the CleaningExample is used in a try-finally block then the
  83  * {@code close} method calls the cleaning action.
  84  * If the {@code close} method is not called, the cleaning action is called
  85  * by the Cleaner when the CleaningExample instance has become phantom reachable.
  86  * <pre>{@code
  87  * public class CleaningExample implements AutoCloseable {
  88  *        // A cleaner, preferably one shared within a library
  89  *        private static final Cleaner cleaner = <cleaner>;
  90  *
  91  *        static class State implements Runnable {
  92  *
  93  *            State(...) {
  94  *                // initialize State needed for cleaning action
  95  *            }
  96  *
  97  *            public void run() {
  98  *                // cleanup action accessing State, executed at most once
  99  *            }
 100  *        }
 101  *
 102  *        private final State;
 103  *        private final Cleaner.Cleanable cleanable
 104  *
 105  *        public CleaningExample() {
 106  *            this.state = new State(...);
 107  *            this.cleanable = cleaner.register(this, state);
 108  *        }
 109  *
 110  *        public void close() {
 111  *            cleanable.clean();
 112  *        }
 113  *    }
 114  * }</pre>
 115  * The cleaning action could be a lambda but all too easily will capture
 116  * the object reference, by referring to fields of the object being cleaned,
 117  * preventing the object from becoming phantom reachable.
 118  * Using a static nested class, as above, will avoid accidentally retaining the
 119  * object reference.
 120  * <p>
 121  * <a name="compatible-cleaners"></a>
 122  * Cleaning actions should be prepared to be invoked concurrently with
 123  * other cleaning actions.
 124  * Typically the cleaning actions should be very quick to execute
 125  * and not block. If the cleaning action blocks, it may delay processing
 126  * other cleaning actions registered to the same cleaner.
 127  * All cleaning actions registered to a cleaner should be mutually compatible.
 128  * @since 9
 129  */
 130 public final class Cleaner {
 131 
 132     /**
 133      * The Cleaner implementation.
 134      */
 135     final CleanerImpl impl;
 136 
 137     static {
 138         CleanerImpl.setCleanerImplAccess((Cleaner c) -> c.impl);
 139     }
 140 
 141     /**
 142      * Construct a Cleaner implementation and start it.
 143      */
 144     private Cleaner() {
 145         impl = new CleanerImpl();
 146     }
 147 
 148     /**
 149      * Returns a new {@code Cleaner}.
 150      * <p>
 151      * The cleaner creates a {@link Thread#setDaemon(boolean) daemon thread}
 152      * to process the phantom reachable objects and to invoke cleaning actions.
 153      * The {@linkplain java.lang.Thread#getContextClassLoader context class loader}
 154      * of the thread is set to the
 155      * {@link ClassLoader#getSystemClassLoader() system class loader}.
 156      * The thread has no permissions, enforced only if a
 157      * {@link java.lang.System#setSecurityManager(SecurityManager) SecurityManager is set}.
 158      * <p>
 159      * The cleaner terminates when it is phantom reachable and all of the
 160      * registered cleaning actions are complete.
 161      *
 162      * @return a new {@code Cleaner}
 163      *
 164      * @throws  SecurityException  if the current thread is not allowed to
 165      *               create or start the thread.
 166      */
 167     public static Cleaner create() {
 168         Cleaner cleaner = new Cleaner();
 169         cleaner.impl.start(cleaner, null);
 170         return cleaner;
 171     }
 172 
 173     /**
 174      * Returns a new {@code Cleaner} using a {@code Thread} from the {@code ThreadFactory}.
 175      * <p>
 176      * A thread from the thread factory's {@link ThreadFactory#newThread(Runnable) newThread}
 177      * method is set to be a {@link Thread#setDaemon(boolean) daemon thread}
 178      * and started to process phantom reachable objects and invoke cleaning actions.
 179      * On each call the {@link ThreadFactory#newThread(Runnable) thread factory}
 180      * must provide a Thread that is suitable for performing the cleaning actions.
 181      * <p>
 182      * The cleaner terminates when it is phantom reachable and all of the
 183      * registered cleaning actions are complete.
 184      *
 185      * @param threadFactory a {@code ThreadFactory} to return a new {@code Thread}
 186      *                      to process cleaning actions
 187      * @return a new {@code Cleaner}
 188      *
 189      * @throws  IllegalThreadStateException  if the thread from the thread
 190      *               factory was {@link Thread.State#NEW not a new thread}.
 191      * @throws  SecurityException  if the current thread is not allowed to
 192      *               create or start the thread.
 193      */
 194     public static Cleaner create(ThreadFactory threadFactory) {
 195         Objects.requireNonNull(threadFactory, "threadFactory");
 196         Cleaner cleaner = new Cleaner();
 197         cleaner.impl.start(cleaner, threadFactory);
 198         return cleaner;
 199     }
 200 
 201     /**
 202      * Registers an object and a cleaning action to run when the object
 203      * becomes phantom reachable.
 204      * Refer to the <a href="#compatible-cleaners">API Note</a> above for
 205      * cautions about the behavior of cleaning actions.
 206      *
 207      * @param obj   the object to monitor
 208      * @param action a {@code Runnable} to invoke when the object becomes phantom reachable
 209      * @return a {@code Cleanable} instance
 210      */
 211     public Cleanable register(Object obj, Runnable action) {
 212         Objects.requireNonNull(obj, "obj");
 213         Objects.requireNonNull(action, "action");
 214         return new CleanerImpl.PhantomCleanableRef(obj, this, action);
 215     }
 216 
 217     /**
 218      * {@code Cleanable} represents an object and a
 219      * cleaning action registered in a {@code Cleaner}.
 220      * @since 9
 221      */
 222     public interface Cleanable {
 223         /**
 224          * Unregisters the cleanable and invokes the cleaning action.
 225          * The cleanable's cleaning action is invoked at most once
 226          * regardless of the number of calls to {@code clean}.
 227          */
 228         void clean();
 229     }
 230 
 231 }