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.Function;
33 
34 // Android-changed: Use the shared SystemCleaner instance on Android.
35 // Android-changed: Exceptions are only ignored by Cleaner.create() threads.
36 /**
37  * {@code Cleaner} manages a set of object references and corresponding cleaning actions.
38  * <p>
39  * Cleaning actions are {@link #register(Object object, Runnable action) registered}
40  * to run after the cleaner is notified that the object has become
41  * phantom reachable.
42  * The cleaner uses {@link PhantomReference} and {@link ReferenceQueue} to be
43  * notified when the <a href="package-summary.html#reachability">reachability</a>
44  * changes.
45  * <p>
46  * Each cleaner operates independently, managing the pending cleaning actions
47  * and handling threading and termination when the cleaner is no longer in use.
48  * Registering an object reference and corresponding cleaning action returns
49  * a {@link Cleanable Cleanable}. The most efficient use is to explicitly invoke
50  * the {@link Cleanable#clean clean} method when the object is closed or
51  * no longer needed.
52  * The cleaning action is a {@link Runnable} to be invoked at most once when
53  * the object has become phantom reachable unless it has already been explicitly cleaned.
54  * Note that the cleaning action must not refer to the object being registered.
55  * If so, the object will not become phantom reachable and the cleaning action
56  * will not be invoked automatically.
57  * <p>
58  * The execution of the cleaning action is performed
59  * by a thread associated with the cleaner.
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  *        // Use the shared android.system.SystemCleaner instance on Android.
89  *        private static final Cleaner cleaner = SystemCleaner.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 id="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 {
CleanerImpl.setCleanerImplAccess(new Function<Cleaner, CleanerImpl>() { @Override public CleanerImpl apply(Cleaner cleaner) { return cleaner.impl; } })138         CleanerImpl.setCleanerImplAccess(new Function<Cleaner, CleanerImpl>() {
139             @Override
140             public CleanerImpl apply(Cleaner cleaner) {
141                 return cleaner.impl;
142             }
143         });
144     }
145 
146     /**
147      * Construct a Cleaner implementation and start it.
148      */
Cleaner()149     private Cleaner() {
150         impl = new CleanerImpl();
151     }
152 
Cleaner(ReferenceQueue queue)153     private Cleaner(ReferenceQueue queue) {
154         impl = new CleanerImpl(queue);
155     }
156 
157     /**
158      * Returns a new {@code Cleaner}.
159      * <p>
160      * The cleaner creates a {@link Thread#setDaemon(boolean) daemon thread}
161      * to process the phantom reachable objects and to invoke cleaning actions.
162      * The {@linkplain java.lang.Thread#getContextClassLoader context class loader}
163      * of the thread is set to the
164      * {@link ClassLoader#getSystemClassLoader() system class loader}.
165      * The thread has no permissions, enforced only if a
166      * {@link java.lang.System#setSecurityManager(SecurityManager) SecurityManager is set}.
167      * <p>
168      * All exceptions thrown by the cleaning actions in this thread are ignored.
169      * <p>
170      * The cleaner terminates when it is phantom reachable and all of the
171      * registered cleaning actions are complete.
172      *
173      * @return a new {@code Cleaner}
174      *
175      * @throws  SecurityException  if the current thread is not allowed to
176      *               create or start the thread.
177      */
create()178     public static Cleaner create() {
179         Cleaner cleaner = new Cleaner();
180         cleaner.impl.start(cleaner, null);
181         return cleaner;
182     }
183 
184     /**
185      * Returns a new {@code Cleaner} using a {@code Thread} from the {@code ThreadFactory}.
186      * <p>
187      * A thread from the thread factory's {@link ThreadFactory#newThread(Runnable) newThread}
188      * method is set to be a {@link Thread#setDaemon(boolean) daemon thread}
189      * and started to process phantom reachable objects and invoke cleaning actions.
190      * On each call the {@link ThreadFactory#newThread(Runnable) thread factory}
191      * must provide a Thread that is suitable for performing the cleaning actions.
192      * <p>
193      * The cleaner terminates when it is phantom reachable and all of the
194      * registered cleaning actions are complete.
195      *
196      * @param threadFactory a {@code ThreadFactory} to return a new {@code Thread}
197      *                      to process cleaning actions
198      * @return a new {@code Cleaner}
199      *
200      * @throws  IllegalThreadStateException  if the thread from the thread
201      *               factory was {@link Thread.State#NEW not a new thread}.
202      * @throws  SecurityException  if the current thread is not allowed to
203      *               create or start the thread.
204      */
create(ThreadFactory threadFactory)205     public static Cleaner create(ThreadFactory threadFactory) {
206         Objects.requireNonNull(threadFactory, "threadFactory");
207         Cleaner cleaner = new Cleaner();
208         cleaner.impl.start(cleaner, threadFactory);
209         return cleaner;
210     }
211 
212     // Android-added: objects registered in the system cleaner are cleaned
213     // by the finalizer daemon thread, not in a InnocuousThread.
214     /**
215      * Returns a new {@code Cleaner} associated with the finalizer thread.
216      * @hide
217      */
createSystemCleaner()218     public static Cleaner createSystemCleaner() {
219         Cleaner cleaner = new Cleaner(FinalizerReference.queue);
220         cleaner.impl.start(cleaner);
221         return cleaner;
222     }
223 
224     /**
225      * Registers an object and a cleaning action to run when the object
226      * becomes phantom reachable.
227      * Refer to the <a href="#compatible-cleaners">API Note</a> above for
228      * cautions about the behavior of cleaning actions.
229      *
230      * @param obj   the object to monitor
231      * @param action a {@code Runnable} to invoke when the object becomes phantom reachable
232      * @return a {@code Cleanable} instance
233      */
register(Object obj, Runnable action)234     public Cleanable register(Object obj, Runnable action) {
235         Objects.requireNonNull(obj, "obj");
236         Objects.requireNonNull(action, "action");
237         return new CleanerImpl.PhantomCleanableRef(obj, this, action);
238     }
239 
240     /**
241      * {@code Cleanable} represents an object and a
242      * cleaning action registered in a {@code Cleaner}.
243      * @since 9
244      */
245     public interface Cleanable {
246         /**
247          * Unregisters the cleanable and invokes the cleaning action.
248          * The cleanable's cleaning action is invoked at most once
249          * regardless of the number of calls to {@code clean}.
250          */
clean()251         void clean();
252     }
253 
254 }
255