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