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 jdk.internal.ref; 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 59 public class Cleaner 60 extends PhantomReference<Object> 61 implements Runnable 62 { 63 64 // Dummy reference queue, needed because the PhantomReference constructor 65 // insists that we pass a queue. Nothing will ever be placed on this queue 66 // since the reference handler invokes cleaners explicitly. 67 // 68 private static final ReferenceQueue<Object> dummyQueue = new ReferenceQueue<>(); 69 70 // Doubly-linked list of live cleaners, which prevents the cleaners 71 // themselves from being GC'd before their referents 72 // 73 private static Cleaner first = null; 74 75 private Cleaner 76 next = null, 77 prev = null; 78 79 private static synchronized Cleaner add(Cleaner cl) { 80 if (first != null) { 81 cl.next = first; 82 first.prev = cl; 83 } 84 first = cl; 85 return cl; 86 } 87 88 private static synchronized boolean remove(Cleaner cl) { 89 90 // If already removed, do nothing 91 if (cl.next == cl) 92 return false; 93 94 // Update list 95 if (first == cl) { 96 if (cl.next != null) 97 first = cl.next; 98 else 99 first = cl.prev; 100 } 101 if (cl.next != null) 102 cl.next.prev = cl.prev; 103 if (cl.prev != null) 104 cl.prev.next = cl.next; 105 106 // Indicate removal by pointing the cleaner to itself 107 cl.next = cl; 108 cl.prev = cl; 109 return true; 110 111 } 112 113 private final Runnable thunk; 114 115 private Cleaner(Object referent, Runnable thunk) { 116 super(referent, dummyQueue); 117 this.thunk = thunk; 118 } 119 120 /** 121 * Creates a new cleaner. 122 * 123 * @param ob the referent object to be cleaned 124 * @param thunk 125 * The cleanup code to be run when the cleaner is invoked. The 126 * cleanup code is run directly from the reference-handler thread, 127 * so it should be as simple and straightforward as possible. 128 * 129 * @return The new cleaner 130 */ 131 public static Cleaner create(Object ob, Runnable thunk) { 132 if (thunk == null) 133 return null; 134 return add(new Cleaner(ob, thunk)); 135 } 136 137 /** 138 * Runs this cleaner, if it has not been run before. 139 */ 140 public void clean() { 141 if (!remove(this)) 142 return; 143 try { 144 thunk.run(); 145 } catch (final Throwable x) { 146 AccessController.doPrivileged(new PrivilegedAction<>() { 147 public Void run() { 148 if (System.err != null) 149 new Error("Cleaner terminated abnormally", x) 150 .printStackTrace(); 151 System.exit(1); 152 return null; 153 }}); 154 } 155 } 156 157 @Override public void run() { 158 SecurityManager security = System.getSecurityManager(); 159 if (security != null) 160 security.checkPackageAccess("jdk.internal.ref"); 161 this.clean(); 162 } 163 164 }