/*
* 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.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 Cleanable#clean invoked} or to be
* {@link Cleanable#clear cleared}.
* The most efficient use is to explicitly invoke the
* {@link Cleanable#clean Cleanable.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:
*
*
{@link #phantomCleanable(Object object, Runnable thunk) phantomCleanable}
* registers the Runnable to be run when the object becomes phantom reachable.
*
{@link #weakCleanable(Object object, Runnable thunk) weakCleanable}
* registers the Runnable to be run when object becomes weakly reachable.
*
{@link #softCleanable(Object object, Runnable thunk) softCleanable}
* registers the Runnable to be run when object becomes softly reachable.
*
*
* 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.
*/
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 Cleanable instance
*/
public Cleanable phantomCleanable(Object obj, Runnable thunk) {
Objects.requireNonNull(obj, "obj");
Objects.requireNonNull(thunk, "thunk");
return new PhantomCleanableRef(obj, this, 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 Cleanable instance
*/
public Cleanable weakCleanable(Object obj, Runnable thunk) {
Objects.requireNonNull(obj, "obj");
Objects.requireNonNull(thunk, "thunk");
return new WeakCleanableRef(obj, this, 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 Cleanable instance
*/
public Cleanable softCleanable(Object obj, Runnable thunk) {
Objects.requireNonNull(obj, "obj");
Objects.requireNonNull(thunk, "thunk");
return new SoftCleanableRef(obj, this, thunk);
}
/**
* CleanerImpl manages the thread and the pending cleanup functions.
*/
static final class CleanerImpl implements Runnable {
// Head of the Cleanable list
private final CleanableList cleanableList;
// The queue of pending cleaning functions
final ReferenceQueue