/* * 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 jdk.internal.ref.CleanerImpl; import java.util.Objects; import java.util.concurrent.ThreadFactory; import java.util.function.Function; // Android-changed: Use the shared SystemCleaner instance on Android. // Android-changed: Exceptions are only ignored by Cleaner.create() threads. /** * {@code Cleaner} manages a set of object references and corresponding cleaning actions. *
* Cleaning actions are {@link #register(Object object, Runnable action) registered} * to run after the cleaner is notified that the object has become * phantom reachable. * The cleaner uses {@link PhantomReference} and {@link ReferenceQueue} to be * notified when the reachability * changes. *
* Each cleaner operates independently, managing the pending cleaning actions * and handling threading and termination when the cleaner is no longer in use. * Registering an object reference and corresponding cleaning action returns * a {@link Cleanable Cleanable}. The most efficient use is to explicitly invoke * the {@link Cleanable#clean clean} method when the object is closed or * no longer needed. * The cleaning action is a {@link Runnable} to be invoked at most once when * the object has become phantom reachable unless it has already been explicitly cleaned. * Note that the cleaning action must not refer to the object being registered. * If so, the object will not become phantom reachable and the cleaning action * will not be invoked automatically. *
* The execution of the cleaning action is performed * by a thread associated with the cleaner. * The thread runs until all registered cleaning actions have * completed and the cleaner itself is reclaimed by the garbage collector. *
* The behavior of cleaners during {@link System#exit(int) System.exit} * is implementation specific. No guarantees are made relating * to whether cleaning actions are invoked or not. *
* Unless otherwise noted, passing a {@code null} argument to a constructor or * method in this class will cause a * {@link java.lang.NullPointerException NullPointerException} to be thrown. * * @apiNote * The cleaning action is invoked only after the associated object becomes * phantom reachable, so it is important that the object implementing the * cleaning action does not hold references to the object. * In this example, a static class encapsulates the cleaning state and action. * An "inner" class, anonymous or not, must not be used because it implicitly * contains a reference to the outer instance, preventing it from becoming * phantom reachable. * The choice of a new cleaner or sharing an existing cleaner is determined * by the use case. *
* If the CleaningExample is used in a try-finally block then the * {@code close} method calls the cleaning action. * If the {@code close} method is not called, the cleaning action is called * by the Cleaner when the CleaningExample instance has become phantom reachable. *
{@code * public class CleaningExample implements AutoCloseable { * // Use the shared android.system.SystemCleaner instance on Android. * private static final Cleaner cleaner = SystemCleaner.cleaner(); * * static class State implements Runnable { * * State(...) { * // initialize State needed for cleaning action * } * * public void run() { * // cleanup action accessing State, executed at most once * } * } * * private final State; * private final Cleaner.Cleanable cleanable * * public CleaningExample() { * this.state = new State(...); * this.cleanable = cleaner.register(this, state); * } * * public void close() { * cleanable.clean(); * } * } * }* The cleaning action could be a lambda but all too easily will capture * the object reference, by referring to fields of the object being cleaned, * preventing the object from becoming phantom reachable. * Using a static nested class, as above, will avoid accidentally retaining the * object reference. *
*
* Cleaning actions should be prepared to be invoked concurrently with
* other cleaning actions.
* Typically the cleaning actions should be very quick to execute
* and not block. If the cleaning action blocks, it may delay processing
* other cleaning actions registered to the same cleaner.
* All cleaning actions registered to a cleaner should be mutually compatible.
* @since 9
*/
public final class Cleaner {
/**
* The Cleaner implementation.
*/
final CleanerImpl impl;
static {
CleanerImpl.setCleanerImplAccess(new Function
* The cleaner creates a {@link Thread#setDaemon(boolean) daemon thread}
* to process the phantom reachable objects and to invoke cleaning actions.
* The {@linkplain java.lang.Thread#getContextClassLoader context class loader}
* of the thread is set to the
* {@link ClassLoader#getSystemClassLoader() system class loader}.
* The thread has no permissions, enforced only if a
* {@link java.lang.System#setSecurityManager(SecurityManager) SecurityManager is set}.
*
* All exceptions thrown by the cleaning actions in this thread are ignored.
*
* The cleaner terminates when it is phantom reachable and all of the
* registered cleaning actions are complete.
*
* @return a new {@code Cleaner}
*
* @throws SecurityException if the current thread is not allowed to
* create or start the thread.
*/
public static Cleaner create() {
Cleaner cleaner = new Cleaner();
cleaner.impl.start(cleaner, null);
return cleaner;
}
/**
* Returns a new {@code Cleaner} using a {@code Thread} from the {@code ThreadFactory}.
*
* A thread from the thread factory's {@link ThreadFactory#newThread(Runnable) newThread}
* method is set to be a {@link Thread#setDaemon(boolean) daemon thread}
* and started to process phantom reachable objects and invoke cleaning actions.
* On each call the {@link ThreadFactory#newThread(Runnable) thread factory}
* must provide a Thread that is suitable for performing the cleaning actions.
*
* The cleaner terminates when it is phantom reachable and all of the
* registered cleaning actions are complete.
*
* @param threadFactory a {@code ThreadFactory} to return a new {@code Thread}
* to process cleaning actions
* @return a new {@code Cleaner}
*
* @throws IllegalThreadStateException if the thread from the thread
* factory was {@link Thread.State#NEW not a new thread}.
* @throws SecurityException if the current thread is not allowed to
* create or start the thread.
*/
public static Cleaner create(ThreadFactory threadFactory) {
Objects.requireNonNull(threadFactory, "threadFactory");
Cleaner cleaner = new Cleaner();
cleaner.impl.start(cleaner, threadFactory);
return cleaner;
}
// Android-added: objects registered in the system cleaner are cleaned
// by the finalizer daemon thread, not in a InnocuousThread.
/**
* Returns a new {@code Cleaner} associated with the finalizer thread.
* @hide
*/
public static Cleaner createSystemCleaner() {
Cleaner cleaner = new Cleaner(FinalizerReference.queue);
cleaner.impl.start(cleaner);
return cleaner;
}
/**
* Registers an object and a cleaning action to run when the object
* becomes phantom reachable.
* Refer to the API Note above for
* cautions about the behavior of cleaning actions.
*
* @param obj the object to monitor
* @param action a {@code Runnable} to invoke when the object becomes phantom reachable
* @return a {@code Cleanable} instance
*/
public Cleanable register(Object obj, Runnable action) {
Objects.requireNonNull(obj, "obj");
Objects.requireNonNull(action, "action");
return new CleanerImpl.PhantomCleanableRef(obj, this, action);
}
/**
* {@code Cleanable} represents an object and a
* cleaning action registered in a {@code Cleaner}.
* @since 9
*/
public interface Cleanable {
/**
* Unregisters the cleanable and invokes the cleaning action.
* The cleanable's cleaning action is invoked at most once
* regardless of the number of calls to {@code clean}.
*/
void clean();
}
}