(original) (raw)

/* * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.lang.ref; import sun.misc.InnocuousThread; import sun.misc.ManagedLocalsThread; import java.lang.InterruptedException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Objects; import java.util.concurrent.ThreadFactory; /** * Cleaner manages a set of object references and corresponding cleanup functions. * Each Cleaner operates independently, managing the pending cleanup functions * and handling threading and termination when the Cleaner is no longer in use. * Registering an object reference and corresponding cleaning function returns * allows the cleaning function to be invoked explicitly * {@link Cleanup#clean invoked} or to be * {@link Cleanup#clear cleared}. * The most efficient use is to explicitly invoke the * {@link Cleanup#clean Cleanup.clean} method when the object * is closed or no longer needed. * The cleaning function is invoked at most once when the object is * no longer reachable unless it has already been explicitly cleaned or cleared. * Note that the cleaning function must not refer to the object being registered. * If so, the object will not become unreachable and the cleaning function * will not be invoked. *

* Cleaning functions are registered as: *

*

* The execution of the cleaning function is performed * by a thread associated with the Cleaner. * The thread runs until all registered cleaning functions have * executed and the Cleaner itself is reclaimed by the garbage collector. * Cleaning functions should be prepared to be executed concurrently with * other cleaning functions. *

* The behavior of the Cleaner during {@link System#exit(int) System.exit} * is implementation specific. No guarantees are made related * to whether cleaning functions are executed or not. * * @author Roger Riggs * @author Kim Barrett * @apiNote Typically the cleaning functions should be very quick to execute * and not block. If the cleaning function blocks it may delay processing * other cleaning functions using the same Cleaner. It is up to the application * to have mutually compatible cleaning functions on a Cleaner. */ public final class Cleaner { /** * The Cleaner implementation. */ private final CleanerImpl impl; /** * Construct a Cleaner implementation and start it. */ private Cleaner() { impl = new CleanerImpl(); } /** * Return a new Cleaner. *

* The Cleaner creates a daemon thread to process the * unreachable objects and to invoke cleaning functions. *

* The Cleaner terminates when it is unreachable and all of the objects * registered are unreachable and corresponding Runnables are complete. * * @return a new Cleaner */ public static Cleaner create() { return create(InnocuousThreadFactory.factory()); } /** * Returns a new Cleaner using a ThreadFactory. * The cleaning functions are processed on a new Thread from the {@link ThreadFactory}. * The Thread is {@link Thread#start started} to process cleaning functions. * The factory should set the Thread attributes as needed for * priority, name, thread group, uncaught exception handler, etc. * The thread is set to be a {@link Thread#setDaemon(boolean) daemon thread}. * The Cleaner uses this daemon thread to process the * unreachable objects and to invoke cleaning functions. *

* The Cleaner terminates when it is unreachable and all of the objects * registered are unreachable and corresponding Runnables are complete. * * @param threadFactory a Thread factory to return a new Thread to * process cleaning functions * @return a new Cleaner */ public static Cleaner create(ThreadFactory threadFactory) { Cleaner cleaner = new Cleaner(); cleaner.impl.start(cleaner, threadFactory); return cleaner; } /** * Registers an object and a Runnable to be run when the object * becomes phantom reachable. * Refer to the class javadoc for cautions about the behavior * of cleaning functions. * * @param obj the object to monitor * @param thunk a Runnable to invoke when the object becomes phantom reachable * @return a Cleanup instance */ public Cleanup phantomCleanup(Object obj, Runnable thunk) { Objects.requireNonNull(obj, "obj"); Objects.requireNonNull(thunk, "thunk"); return impl.phantomCleanup(obj, thunk); } /** * Registers an object and a Runnable to be run when the object * becomes weakly reachable. * Refer to the class javadoc for cautions about the behavior * of cleaning functions. * * @param obj the object to monitor * @param thunk a Runnable to invoke when the object becomes weakly reachable * @return a Cleanup instance */ public Cleanup weakCleanup(Object obj, Runnable thunk) { Objects.requireNonNull(obj, "obj"); Objects.requireNonNull(thunk, "thunk"); return impl.weakCleanup(obj, thunk); } /** * Registers an object and a Runnable to be run when the object * becomes softly reachable. * Refer to the class javadoc for cautions about the behavior * of cleaning functions. * * @param obj the object to monitorss * @param thunk a Runnable to invoke when the object becomes softly reachable * @return a Cleanup instance */ public Cleanup softCleanup(Object obj, Runnable thunk) { Objects.requireNonNull(obj, "obj"); Objects.requireNonNull(thunk, "thunk"); return impl.softCleanup(obj, thunk); } /** * CleanerImpl manages the thread and the pending cleanup functions. */ private static final class CleanerImpl implements Runnable { // Head of the Cleanup list private final CleanupRef cleanupList; // The queue of pending cleaning functions private final ReferenceQueue