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 jdk.internal.ref.CleanerImpl;
  29 
  30 import java.util.Objects;
  31 import java.util.concurrent.ThreadFactory;
  32 import java.util.function.Consumer;
  33 import java.util.function.Function;
  34 import java.util.function.LongConsumer;
  35 import java.util.function.LongSupplier;
  36 import java.util.function.Supplier;
  37 
  38 /**
  39  * {@code Cleaner} manages a set of object references and corresponding cleaning actions.
  40  * <p>
  41  * Cleaning actions are {@link #register(Object object, Runnable action) registered}
  42  * to run after the cleaner is notified that the object has become
  43  * phantom reachable.
  44  * The cleaner uses {@link PhantomReference} and {@link ReferenceQueue} to be
  45  * notified when the <a href="package-summary.html#reachability">reachability</a>
  46  * changes.
  47  * <p>
  48  * Each cleaner operates independently, managing the pending cleaning actions
  49  * and handling threading and termination when the cleaner is no longer in use.
  50  * Registering an object reference and corresponding cleaning action returns
  51  * a {@link Cleanable Cleanable}. The most efficient use is to explicitly invoke
  52  * the {@link Cleanable#clean clean} method when the object is closed or
  53  * no longer needed.
  54  * The cleaning action is a {@link Runnable} to be invoked at most once when
  55  * the object has become phantom reachable unless it has already been explicitly cleaned.
  56  * Note that the cleaning action must not refer to the object being registered.
  57  * If so, the object will not become phantom reachable and the cleaning action
  58  * will not be invoked automatically.
  59  * <p>
  60  * The execution of the cleaning action is performed
  61  * by a thread associated with the cleaner.
  62  * All exceptions thrown by the cleaning action are ignored.
  63  * The cleaner and other cleaning actions are not affected by
  64  * exceptions in a cleaning action.
  65  * The thread runs until all registered cleaning actions have
  66  * completed and the cleaner itself is reclaimed by the garbage collector.
  67  * <p>
  68  * The behavior of cleaners during {@link System#exit(int) System.exit}
  69  * is implementation specific. No guarantees are made relating
  70  * to whether cleaning actions are invoked or not.
  71  * <p>
  72  * Unless otherwise noted, passing a {@code null} argument to a constructor or
  73  * method in this class will cause a
  74  * {@link java.lang.NullPointerException NullPointerException} to be thrown.
  75  *
  76  * @apiNote
  77  * The cleaning action is invoked only after the associated object becomes
  78  * phantom reachable, so it is important that the object implementing the
  79  * cleaning action does not hold references to the object.
  80  * In this example, a static class encapsulates the cleaning state and action.
  81  * An "inner" class, anonymous or not,  must not be used because it implicitly
  82  * contains a reference to the outer instance, preventing it from becoming
  83  * phantom reachable.
  84  * The choice of a new cleaner or sharing an existing cleaner is determined
  85  * by the use case.
  86  * <p>
  87  * If the CleaningExample is used in a try-finally block then the
  88  * {@code close} method calls the cleaning action.
  89  * If the {@code close} method is not called, the cleaning action is called
  90  * by the Cleaner when the CleaningExample instance has become phantom reachable.
  91  * <pre>{@code
  92  * public class CleaningExample implements AutoCloseable {
  93  *        // A cleaner, preferably one shared within a library
  94  *        private static final Cleaner cleaner = <cleaner>;
  95  *
  96  *        static class State implements Runnable {
  97  *
  98  *            State(...) {
  99  *                // initialize State needed for cleaning action
 100  *            }
 101  *
 102  *            public void run() {
 103  *                // cleanup action accessing State, executed at most once
 104  *            }
 105  *        }
 106  *
 107  *        private final State;
 108  *        private final Cleaner.Cleanable cleanable
 109  *
 110  *        public CleaningExample() {
 111  *            this.state = new State(...);
 112  *            this.cleanable = cleaner.register(this, state);
 113  *        }
 114  *
 115  *        public void close() {
 116  *            cleanable.clean();
 117  *        }
 118  *    }
 119  * }</pre>
 120  * The cleaning action could be a lambda but all too easily will capture
 121  * the object reference, by referring to fields of the object being cleaned,
 122  * preventing the object from becoming phantom reachable.
 123  * Using a static nested class, as above, will avoid accidentally retaining the
 124  * object reference.
 125  * <p>
 126  * <a id="compatible-cleaners"></a>
 127  * Cleaning actions should be prepared to be invoked concurrently with
 128  * other cleaning actions.
 129  * Typically the cleaning actions should be very quick to execute
 130  * and not block. If the cleaning action blocks, it may delay processing
 131  * other cleaning actions registered to the same cleaner.
 132  * All cleaning actions registered to a cleaner should be mutually compatible.
 133  * @since 9
 134  */
 135 public final class Cleaner {
 136 
 137     /**
 138      * The Cleaner implementation.
 139      */
 140     final CleanerImpl impl;
 141 
 142     static {
 143         CleanerImpl.setCleanerImplAccess(new Function<Cleaner, CleanerImpl>() {
 144             @Override
 145             public CleanerImpl apply(Cleaner cleaner) {
 146                 return cleaner.impl;
 147             }
 148         });
 149     }
 150 
 151     /**
 152      * Construct a Cleaner implementation and start it.
 153      */
 154     private Cleaner() {
 155         impl = new CleanerImpl();
 156     }
 157 
 158     /**
 159      * Returns a new {@code Cleaner}.
 160      * <p>
 161      * The cleaner creates a {@link Thread#setDaemon(boolean) daemon thread}
 162      * to process the phantom reachable objects and to invoke cleaning actions.
 163      * The {@linkplain java.lang.Thread#getContextClassLoader context class loader}
 164      * of the thread is set to the
 165      * {@link ClassLoader#getSystemClassLoader() system class loader}.
 166      * The thread has no permissions, enforced only if a
 167      * {@link java.lang.System#setSecurityManager(SecurityManager) SecurityManager is set}.
 168      * <p>
 169      * The cleaner terminates when it is phantom reachable and all of the
 170      * registered cleaning actions are complete.
 171      *
 172      * @return a new {@code Cleaner}
 173      *
 174      * @throws  SecurityException  if the current thread is not allowed to
 175      *               create or start the thread.
 176      */
 177     public static Cleaner create() {
 178         Cleaner cleaner = new Cleaner();
 179         cleaner.impl.start(cleaner, null);
 180         return cleaner;
 181     }
 182 
 183     /**
 184      * Returns a new {@code Cleaner} using a {@code Thread} from the {@code ThreadFactory}.
 185      * <p>
 186      * A thread from the thread factory's {@link ThreadFactory#newThread(Runnable) newThread}
 187      * method is set to be a {@link Thread#setDaemon(boolean) daemon thread}
 188      * and started to process phantom reachable objects and invoke cleaning actions.
 189      * On each call the {@link ThreadFactory#newThread(Runnable) thread factory}
 190      * must provide a Thread that is suitable for performing the cleaning actions.
 191      * <p>
 192      * The cleaner terminates when it is phantom reachable and all of the
 193      * registered cleaning actions are complete.
 194      *
 195      * @param threadFactory a {@code ThreadFactory} to return a new {@code Thread}
 196      *                      to process cleaning actions
 197      * @return a new {@code Cleaner}
 198      *
 199      * @throws  IllegalThreadStateException  if the thread from the thread
 200      *               factory was {@link Thread.State#NEW not a new thread}.
 201      * @throws  SecurityException  if the current thread is not allowed to
 202      *               create or start the thread.
 203      */
 204     public static Cleaner create(ThreadFactory threadFactory) {
 205         Objects.requireNonNull(threadFactory, "threadFactory");
 206         Cleaner cleaner = new Cleaner();
 207         cleaner.impl.start(cleaner, threadFactory);
 208         return cleaner;
 209     }
 210 
 211     /**
 212      * Registers an object and a cleaning action to run when the object
 213      * becomes phantom reachable.
 214      * Refer to the <a href="#compatible-cleaners">API Note</a> above for
 215      * cautions about the behavior of cleaning actions.
 216      *
 217      * @param obj   the object to monitor
 218      * @param action a {@code Runnable} to invoke when the object becomes phantom reachable
 219      * @return a {@code Cleanable} instance
 220      */
 221     public Cleanable register(Object obj, Runnable action) {
 222         Objects.requireNonNull(obj, "obj");
 223         Objects.requireNonNull(action, "action");
 224         return new CleanerImpl.PhantomCleanableRef(obj, this, action);
 225     }
 226 
 227     /**
 228      * {@code Cleanable} represents an object and a
 229      * cleaning action registered in a {@code Cleaner}.
 230      * @since 9
 231      */
 232     public interface Cleanable {
 233         /**
 234          * Unregisters the cleanable and invokes the cleaning action.
 235          * The cleanable's cleaning action is invoked at most once
 236          * regardless of the number of calls to {@code clean}.
 237          */
 238         void clean();
 239     }
 240 
 241     /**
 242      * 1st registers an object then allocates a reference-valued resource by
 243      * invoking resource allocator function and associates it with de-allocator
 244      * function which will be called with the resource as cleaning action when
 245      * the registered object becomes phantom reachable.<p>
 246      * Using this method (when applicable) is preferable to using
 247      * {@link #register(Object, Runnable)}, because it ensures correct
 248      * order of actions - 1st register the object, then allocate the resource -
 249      * which prevents resource leaks in rare circumstances when registration fails
 250      * because of insufficient heap memory. The resource allocator function still
 251      * bares all the responsibility for either returning normally with the
 252      * allocated resource or throwing an unchecked exception in which case the
 253      * resource should not be allocated or should already be de-allocated, because
 254      * in such case, the de-allocator function is not called.
 255      * Refer to the <a href="#compatible-cleaners">API Note</a> above for
 256      * cautions about the behavior of cleaning actions.
 257      *
 258      * @param obj                 the object to monitor
 259      * @param resourceAllocator   the resource allocator function
 260      * @param resourceDeallocator the resource de-allocator function, invoked as
 261      *                            cleaning action with the allocated resource
 262      * @param <T>                 the type of resource
 263      * @return a {@link CleanableResource} instance holding the allocated resource
 264      * with associated de-allocator function as cleaning action
 265      * @since 10
 266      */
 267     public <T> CleanableResource<T> createResource(
 268         Object obj,
 269         Supplier<? extends T> resourceAllocator,
 270         Consumer<? super T> resourceDeallocator)
 271     {
 272         Objects.requireNonNull(obj, "obj");
 273         Objects.requireNonNull(resourceAllocator, "resourceConstructor");
 274         Objects.requireNonNull(resourceDeallocator, "resourceDestructor");
 275         return new CleanerImpl.PhantomCleanableResource<>(obj, this, resourceAllocator, resourceDeallocator);
 276     }
 277 
 278     /**
 279      * {@code CleanableResource} represents an object holding some reference
 280      * valued resource and a cleaning action for the resource registered in a
 281      * {@code Cleaner}.
 282      *
 283      * @since 10
 284      *
 285      * @param <T> the type of allocated resource
 286      */
 287     public interface CleanableResource<T> extends Cleanable {
 288         /**
 289          * Obtains the allocated resource.
 290          *
 291          * @return the allocated resource
 292          * @throws IllegalStateException if the resource has already been
 293          *                               {@link #clean() cleaned}
 294          */
 295         T value();
 296     }
 297 
 298     /**
 299      * 1st registers an object then allocates a {@code long}-valued resource by
 300      * invoking resource allocator function and associates it with de-allocator
 301      * function which will be called with the resource as cleaning action when
 302      * the registered object becomes phantom reachable.<p>
 303      * Using this method (when applicable) is preferable to using
 304      * {@link #register(Object, Runnable)}, because it ensures correct
 305      * order of actions - 1st register the object, then allocate the resource -
 306      * which prevents resource leaks in rare circumstances when registration fails
 307      * because of insufficient heap memory. The resource allocator function still
 308      * bares all the responsibility for either returning normally with the
 309      * allocated resource or throwing an unchecked exception in which case the
 310      * resource should not be allocated or should already be de-allocated, because
 311      * in such case, the de-allocator function is not called.
 312      * Refer to the <a href="#compatible-cleaners">API Note</a> above for
 313      * cautions about the behavior of cleaning actions.
 314      *
 315      * @param obj                 the object to monitor
 316      * @param resourceAllocator   the resource allocator function
 317      * @param resourceDeallocator the resource de-allocator function, invoked as
 318      *                            cleaning action with the allocated resource
 319      * @return a {@link LongCleanableResource} instance holding the allocated resource
 320      * with associated de-allocator function as cleaning action
 321      * @since 10
 322      */
 323     public LongCleanableResource createLongResource(
 324         Object obj,
 325         LongSupplier resourceAllocator,
 326         LongConsumer resourceDeallocator)
 327     {
 328         Objects.requireNonNull(obj, "obj");
 329         Objects.requireNonNull(resourceAllocator, "resourceConstructor");
 330         Objects.requireNonNull(resourceDeallocator, "resourceDestructor");
 331         return new CleanerImpl.PhantomLongCleanableResource(obj, this, resourceAllocator, resourceDeallocator);
 332     }
 333 
 334     /**
 335      * {@code LongCleanableResource} represents an object holding some {@code long}
 336      * valued resource and a cleaning action for the resource registered in a
 337      * {@code Cleaner}.
 338      *
 339      * @since 10
 340      */
 341     public interface LongCleanableResource extends Cleanable {
 342         /**
 343          * Obtains the allocated resource.
 344          *
 345          * @return the allocated resource
 346          * @throws IllegalStateException if the resource has already been
 347          *                               {@link #clean() cleaned}
 348          */
 349         long value();
 350     }
 351 }