1 /* 2 * Copyright (c) 1997, 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 java.lang.ref; 27 28 import sun.misc.ManagedLocalsThread; 29 import sun.misc.SharedSecrets; 30 import sun.misc.VM; 31 32 import java.security.AccessController; 33 import java.security.PrivilegedAction; 34 35 /* Package-private; must be in same package as the Reference class */ 36 class Finalizer<T> extends FinalReference<T> implements Cleaner { 37 38 Finalizer(T finalizee) { 39 super(finalizee, null); 40 } 41 42 /** Invoked by VM for objects overriding finalize() method */ 43 static void register(Object finalizee) { 44 Finalizer<?> finalizer = new Finalizer<>(finalizee); 45 finalizer.link(); 46 } 47 48 @Override 49 public void clean() { 50 T finalizee = delete(); 51 if (finalizee == null) { 52 return; 53 } 54 unlink(); 55 try { 56 if (!(finalizee instanceof java.lang.Enum)) { 57 invokeFinalizee(finalizee); 58 } 59 } catch (Throwable x) { } 60 finalizee = null; 61 } 62 63 /* Invoke the finalize() method on the finalizee (overridden by Finalizator) */ 64 void invokeFinalizee(T finalizee) throws Throwable { 65 SharedSecrets.getJavaLangAccess().invokeFinalize(finalizee); 66 finalizee = null; 67 } 68 69 @Override 70 public void clear() { 71 T finalizee = delete(); 72 if (finalizee == null) { 73 return; 74 } 75 unlink(); 76 /* Clear stack slot containing this variable, to decrease 77 the chances of false retention with a conservative GC */ 78 finalizee = null; 79 } 80 81 /* Create a privileged secondary finalizer thread in the system thread 82 group for the given Runnable, and wait for it to complete. 83 84 This method is used by both runFinalization and runFinalizersOnExit. 85 The former method invokes all pending finalizers, while the latter 86 invokes all uninvoked finalizers if on-exit finalization has been 87 enabled. 88 89 These two methods could have been implemented by offloading their work 90 to the regular finalizer thread and waiting for that thread to finish. 91 The advantage of creating a fresh thread, however, is that it insulates 92 invokers of these methods from a stalled or deadlocked finalizer thread. 93 */ 94 private static void forkSecondaryFinalizer(final Runnable proc) { 95 AccessController.doPrivileged( 96 new PrivilegedAction<>() { 97 public Void run() { 98 ThreadGroup tg = Thread.currentThread().getThreadGroup(); 99 for (ThreadGroup tgn = tg; 100 tgn != null; 101 tg = tgn, tgn = tg.getParent()); 102 Thread sft = new ManagedLocalsThread(tg, proc, "Secondary finalizer"); 103 sft.start(); 104 try { 105 sft.join(); 106 } catch (InterruptedException x) { 107 Thread.currentThread().interrupt(); 108 } 109 return null; 110 }}); 111 } 112 113 /* Called by Runtime.runFinalization() */ 114 static void runFinalization() { 115 if (!VM.isBooted()) { 116 return; 117 } 118 119 forkSecondaryFinalizer(new Runnable() { 120 private volatile boolean running; 121 public void run() { 122 // in case of recursive call to run() 123 if (running) 124 return; 125 running = true; 126 ReferenceHandling.runFinalization(); 127 } 128 }); 129 } 130 131 /* Invoked by java.lang.Shutdown */ 132 static void runAllFinalizers() { 133 if (!VM.isBooted()) { 134 return; 135 } 136 137 forkSecondaryFinalizer(new Runnable() { 138 private volatile boolean running; 139 public void run() { 140 // in case of recursive call to run() 141 if (running) 142 return; 143 running = true; 144 for (DLList ucList : uncleanedLists) 145 for (Reference<?> f = ucList.first(); f != null; f = ucList.succ(f)) { 146 ((Cleaner)f).clean(); 147 }}}); 148 } 149 150 /** 151 * Atomically clear the Finalizer and return the finalizee. 152 * 153 * @return the finalizee or null 154 */ 155 private T delete() { 156 T referent = getReferentVolatile(); 157 return (referent != null) && casReferent(referent, null) 158 ? referent : null; 159 } 160 161 // Methods and state that enable Finalizer to be an element of DLList 162 163 /** A constructor used for special Reference instances used in DLList */ 164 Finalizer(boolean setPrevToSelf, boolean setNextToSelf) { 165 super(null, null); 166 if (setPrevToSelf) prevDll = this; 167 if (setNextToSelf) nextDll = this; 168 } 169 170 @SuppressWarnings("unused") // assigned through Unsafe 171 private volatile Reference<?> prevDll, nextDll; 172 173 boolean isDeletedDll() { 174 return getReferentVolatile() == null; 175 } 176 177 Reference<?> getPrevDll() { 178 return prevDll; 179 } 180 181 void lazySetPrevDll(Reference<?> val) { 182 UNSAFE.putOrderedObject(this, PREV_DLL, val); 183 } 184 185 boolean casPrevDll(Reference<?> cmp, Reference<?> val) { 186 return UNSAFE.compareAndSwapObject(this, PREV_DLL, cmp, val); 187 } 188 189 Reference<?> getNextDll() { 190 return nextDll; 191 } 192 193 void lazySetNextDll(Reference<?> val) { 194 UNSAFE.putOrderedObject(this, NEXT_DLL, val); 195 } 196 197 boolean casNextDll(Reference<?> cmp, Reference<?> val) { 198 return UNSAFE.compareAndSwapObject(this, NEXT_DLL, cmp, val); 199 } 200 201 // Unsafe machinery 202 203 private static final sun.misc.Unsafe UNSAFE; 204 private static final long PREV_DLL; 205 private static final long NEXT_DLL; 206 207 static { 208 try { 209 UNSAFE = sun.misc.Unsafe.getUnsafe(); 210 Class<Finalizer> fc = Finalizer.class; 211 PREV_DLL = UNSAFE.objectFieldOffset(fc.getDeclaredField("prevDll")); 212 NEXT_DLL = UNSAFE.objectFieldOffset(fc.getDeclaredField("nextDll")); 213 } catch (Exception e) { 214 throw new Error(e); 215 } 216 } 217 }