1 /* 2 * Copyright (c) 2003, 2013, 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 sun.misc; 27 28 import java.lang.ref.*; 29 import java.security.AccessController; 30 import java.security.PrivilegedAction; 31 32 33 /** 34 * General-purpose phantom-reference-based cleaners. 35 * 36 * <p> Cleaners are a lightweight and more robust alternative to finalization. 37 * They are lightweight because they are not created by the VM and thus do not 38 * require a JNI upcall to be created, and because their cleanup code is 39 * invoked directly by the reference-handler thread rather than by the 40 * finalizer thread. They are more robust because they use phantom references, 41 * the weakest type of reference object, thereby avoiding the nasty ordering 42 * problems inherent to finalization. 43 * 44 * <p> A cleaner tracks a referent object and encapsulates a thunk of arbitrary 45 * cleanup code. Some time after the GC detects that a cleaner's referent has 46 * become phantom-reachable, the reference-handler thread will run the cleaner. 47 * Cleaners may also be invoked directly; they are thread safe and ensure that 48 * they run their thunks at most once. 49 * 50 * <p> Cleaners are not a replacement for finalization. They should be used 51 * only when the cleanup code is extremely simple and straightforward. 52 * Nontrivial cleaners are inadvisable since they risk blocking the 53 * reference-handler thread and delaying further cleanup and finalization. 54 * 55 * 56 * @author Mark Reinhold 57 */ 58 public class Cleaner 59 extends PhantomReference<Object> 60 { 61 62 // Dummy reference queue, needed because the PhantomReference constructor 63 // insists that we pass a queue. Nothing will ever be placed on this queue 64 // since the reference handler invokes cleaners explicitly. 65 // 66 private static final ReferenceQueue<Object> dummyQueue = new ReferenceQueue<>(); 67 68 // Doubly-linked list of live cleaners, which prevents the cleaners 69 // themselves from being GC'd before their referents 70 // 71 static private Cleaner first = null; 72 73 private Cleaner 74 next = null, 75 prev = null; 76 add(Cleaner cl)77 private static synchronized Cleaner add(Cleaner cl) { 78 if (first != null) { 79 cl.next = first; 80 first.prev = cl; 81 } 82 first = cl; 83 return cl; 84 } 85 remove(Cleaner cl)86 private static synchronized boolean remove(Cleaner cl) { 87 88 // If already removed, do nothing 89 if (cl.next == cl) 90 return false; 91 92 // Update list 93 if (first == cl) { 94 if (cl.next != null) 95 first = cl.next; 96 else 97 first = cl.prev; 98 } 99 if (cl.next != null) 100 cl.next.prev = cl.prev; 101 if (cl.prev != null) 102 cl.prev.next = cl.next; 103 104 // Indicate removal by pointing the cleaner to itself 105 cl.next = cl; 106 cl.prev = cl; 107 return true; 108 109 } 110 111 private final Runnable thunk; 112 Cleaner(Object referent, Runnable thunk)113 private Cleaner(Object referent, Runnable thunk) { 114 super(referent, dummyQueue); 115 this.thunk = thunk; 116 } 117 118 // BEGIN Android-added: Support for timeout reporting and error checking. 119 /** 120 * Is q our placeholder queue? 121 * @hide 122 */ isCleanerQueue(ReferenceQueue q)123 public static boolean isCleanerQueue(ReferenceQueue q) { 124 return q == dummyQueue; 125 } 126 127 /** 128 * Check that our placeholder queue is empty, as it always should be. 129 * @hide 130 */ checkCleanerQueueEmpty()131 public static void checkCleanerQueueEmpty() { 132 if (dummyQueue.poll() != null) { 133 throw new AssertionError("Unexpectly nonempty Cleaner placeholder queue"); 134 } 135 } 136 137 /** 138 * Retrieve thunk. 139 * @hide 140 */ getThunk()141 public Runnable getThunk() { 142 return thunk; 143 } 144 // END Android-added: Support for Timeout reporting and error checking. 145 146 /** 147 * Creates a new cleaner. 148 * 149 * @param ob the referent object to be cleaned 150 * @param thunk 151 * The cleanup code to be run when the cleaner is invoked. The 152 * cleanup code is run directly from the reference-handler thread, 153 * so it should be as simple and straightforward as possible. 154 * 155 * @return The new cleaner 156 */ create(Object ob, Runnable thunk)157 public static Cleaner create(Object ob, Runnable thunk) { 158 if (thunk == null) 159 return null; 160 return add(new Cleaner(ob, thunk)); 161 } 162 163 /** 164 * Runs this cleaner, if it has not been run before. 165 */ clean()166 public void clean() { 167 if (!remove(this)) 168 return; 169 try { 170 thunk.run(); 171 } catch (final Throwable x) { 172 AccessController.doPrivileged(new PrivilegedAction<Void>() { 173 public Void run() { 174 if (System.err != null) 175 new Error("Cleaner terminated abnormally", x) 176 .printStackTrace(); 177 System.exit(1); 178 return null; 179 }}); 180 } 181 } 182 183 } 184