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 java.security.PrivilegedAction; 29 import java.security.AccessController; 30 import sun.misc.JavaLangAccess; 31 import sun.misc.ManagedLocalsThread; 32 import sun.misc.SharedSecrets; 33 import sun.misc.VM; 34 35 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in 36 same package as the Reference 37 class */ 38 39 private static ReferenceQueue<Object> queue = new ReferenceQueue<>(); 40 private static Finalizer unfinalized = null; 41 private static final Object lock = new Object(); 42 43 private Finalizer 44 next = null, 45 prev = null; 46 47 private boolean hasBeenFinalized() { 48 return (next == this); 49 } 50 51 private void add() { 52 synchronized (lock) { 53 if (unfinalized != null) { 54 this.next = unfinalized; 55 unfinalized.prev = this; 56 } 57 unfinalized = this; 58 } 59 } 60 61 private void remove() { 62 synchronized (lock) { 63 if (unfinalized == this) { 64 if (this.next != null) { 65 unfinalized = this.next; 66 } else { 67 unfinalized = this.prev; 68 } 69 } 70 if (this.next != null) { 71 this.next.prev = this.prev; 72 } 73 if (this.prev != null) { 74 this.prev.next = this.next; 75 } 76 this.next = this; /* Indicates that this has been finalized */ 77 this.prev = this; 78 } 79 } 80 81 private Finalizer(Object finalizee) { 82 super(finalizee, queue); 83 add(); 84 } 85 86 /* Invoked by VM */ 87 static void register(Object finalizee) { 88 new Finalizer(finalizee); 89 } 90 91 private void runFinalizer(JavaLangAccess jla) { 92 synchronized (this) { 93 if (hasBeenFinalized()) return; 94 remove(); 95 } 96 try { 97 Object finalizee = this.get(); 98 if (finalizee != null && !(finalizee instanceof java.lang.Enum)) { 99 jla.invokeFinalize(finalizee); 100 101 /* Clear stack slot containing this variable, to decrease 102 the chances of false retention with a conservative GC */ 103 finalizee = null; 104 } 105 } catch (Throwable x) { } 106 super.clear(); 107 } 108 109 /* Create a privileged secondary finalizer thread in the system thread 110 group for the given Runnable, and wait for it to complete. 111 112 This method is used by both runFinalization and runFinalizersOnExit. 113 The former method invokes all pending finalizers, while the latter 114 invokes all uninvoked finalizers if on-exit finalization has been 115 enabled. 116 117 These two methods could have been implemented by offloading their work 118 to the regular finalizer thread and waiting for that thread to finish. 119 The advantage of creating a fresh thread, however, is that it insulates 120 invokers of these methods from a stalled or deadlocked finalizer thread. 121 */ 122 private static void forkSecondaryFinalizer(final Runnable proc) { 123 AccessController.doPrivileged( 124 new PrivilegedAction<>() { 125 public Void run() { 126 ThreadGroup tg = Thread.currentThread().getThreadGroup(); 127 for (ThreadGroup tgn = tg; 133 sft.join(); 134 } catch (InterruptedException x) { 135 Thread.currentThread().interrupt(); 136 } 137 return null; 138 }}); 139 } 140 141 /* Called by Runtime.runFinalization() */ 142 static void runFinalization() { 143 if (!VM.isBooted()) { 144 return; 145 } 146 147 forkSecondaryFinalizer(new Runnable() { 148 private volatile boolean running; 149 public void run() { 150 // in case of recursive call to run() 151 if (running) 152 return; 153 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); 154 running = true; 155 for (;;) { 156 Finalizer f = (Finalizer)queue.poll(); 157 if (f == null) break; 158 f.runFinalizer(jla); 159 } 160 } 161 }); 162 } 163 164 /* Invoked by java.lang.Shutdown */ 165 static void runAllFinalizers() { 166 if (!VM.isBooted()) { 167 return; 168 } 169 170 forkSecondaryFinalizer(new Runnable() { 171 private volatile boolean running; 172 public void run() { 173 // in case of recursive call to run() 174 if (running) 175 return; 176 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); 177 running = true; 178 for (;;) { 179 Finalizer f; 180 synchronized (lock) { 181 f = unfinalized; 182 if (f == null) break; 183 unfinalized = f.next; 184 } 185 f.runFinalizer(jla); 186 }}}); 187 } 188 189 private static class FinalizerThread extends ManagedLocalsThread { 190 private volatile boolean running; 191 FinalizerThread(ThreadGroup g) { 192 super(g, "Finalizer"); 193 } 194 public void run() { 195 // in case of recursive call to run() 196 if (running) 197 return; 198 199 // Finalizer thread starts before System.initializeSystemClass 200 // is called. Wait until JavaLangAccess is available 201 while (!VM.isBooted()) { 202 // delay until VM completes initialization 203 try { 204 VM.awaitBooted(); 205 } catch (InterruptedException x) { 206 // ignore and continue 207 } 208 } 209 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); 210 running = true; 211 for (;;) { 212 try { 213 Finalizer f = (Finalizer)queue.remove(); 214 f.runFinalizer(jla); 215 } catch (InterruptedException x) { 216 // ignore and continue 217 } 218 } 219 } 220 } 221 222 static { 223 ThreadGroup tg = Thread.currentThread().getThreadGroup(); 224 for (ThreadGroup tgn = tg; 225 tgn != null; 226 tg = tgn, tgn = tg.getParent()); 227 Thread finalizer = new FinalizerThread(tg); 228 finalizer.setPriority(Thread.MAX_PRIORITY - 2); 229 finalizer.setDaemon(true); 230 finalizer.start(); 231 } 232 233 } | 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; 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 } |