src/java.base/share/classes/java/lang/ref/Finalizer.java

Print this page




  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 jdk.internal.misc.JavaLangAccess;
  31 import jdk.internal.misc.SharedSecrets;
  32 import sun.misc.ManagedLocalsThread;
  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) {


 114        group for the given Runnable, and wait for it to complete.
 115 
 116        This method is used by both runFinalization and runFinalizersOnExit.
 117        The former method invokes all pending finalizers, while the latter
 118        invokes all uninvoked finalizers if on-exit finalization has been
 119        enabled.
 120 
 121        These two methods could have been implemented by offloading their work
 122        to the regular finalizer thread and waiting for that thread to finish.
 123        The advantage of creating a fresh thread, however, is that it insulates
 124        invokers of these methods from a stalled or deadlocked finalizer thread.
 125      */
 126     private static void forkSecondaryFinalizer(final Runnable proc) {
 127         AccessController.doPrivileged(
 128             new PrivilegedAction<>() {
 129                 public Void run() {
 130                     ThreadGroup tg = Thread.currentThread().getThreadGroup();
 131                     for (ThreadGroup tgn = tg;
 132                          tgn != null;
 133                          tg = tgn, tgn = tg.getParent());
 134                     Thread sft = new ManagedLocalsThread(tg, proc, "Secondary finalizer");
 135                     sft.start();
 136                     try {
 137                         sft.join();
 138                     } catch (InterruptedException x) {
 139                         Thread.currentThread().interrupt();
 140                     }
 141                     return null;
 142                 }});
 143     }
 144 
 145     /* Called by Runtime.runFinalization() */
 146     static void runFinalization() {
 147         if (!VM.isBooted()) {
 148             return;
 149         }
 150 
 151         forkSecondaryFinalizer(new Runnable() {
 152             private volatile boolean running;
 153             public void run() {
 154                 // in case of recursive call to run()


 173 
 174         forkSecondaryFinalizer(new Runnable() {
 175             private volatile boolean running;
 176             public void run() {
 177                 // in case of recursive call to run()
 178                 if (running)
 179                     return;
 180                 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
 181                 running = true;
 182                 for (;;) {
 183                     Finalizer f;
 184                     synchronized (lock) {
 185                         f = unfinalized;
 186                         if (f == null) break;
 187                         unfinalized = f.next;
 188                     }
 189                     f.runFinalizer(jla);
 190                 }}});
 191     }
 192 
 193     private static class FinalizerThread extends ManagedLocalsThread {
 194         private volatile boolean running;
 195         FinalizerThread(ThreadGroup g) {
 196             super(g, "Finalizer");
 197         }
 198         public void run() {
 199             // in case of recursive call to run()
 200             if (running)
 201                 return;
 202 
 203             // Finalizer thread starts before System.initializeSystemClass
 204             // is called.  Wait until JavaLangAccess is available
 205             while (!VM.isBooted()) {
 206                 // delay until VM completes initialization
 207                 try {
 208                     VM.awaitBooted();
 209                 } catch (InterruptedException x) {
 210                     // ignore and continue
 211                 }
 212             }
 213             final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
 214             running = true;
 215             for (;;) {
 216                 try {




  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 jdk.internal.misc.JavaLangAccess;
  31 import jdk.internal.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) {


 113        group for the given Runnable, and wait for it to complete.
 114 
 115        This method is used by both runFinalization and runFinalizersOnExit.
 116        The former method invokes all pending finalizers, while the latter
 117        invokes all uninvoked finalizers if on-exit finalization has been
 118        enabled.
 119 
 120        These two methods could have been implemented by offloading their work
 121        to the regular finalizer thread and waiting for that thread to finish.
 122        The advantage of creating a fresh thread, however, is that it insulates
 123        invokers of these methods from a stalled or deadlocked finalizer thread.
 124      */
 125     private static void forkSecondaryFinalizer(final Runnable proc) {
 126         AccessController.doPrivileged(
 127             new PrivilegedAction<>() {
 128                 public Void run() {
 129                     ThreadGroup tg = Thread.currentThread().getThreadGroup();
 130                     for (ThreadGroup tgn = tg;
 131                          tgn != null;
 132                          tg = tgn, tgn = tg.getParent());
 133                     Thread sft = new Thread(tg, proc, "Secondary finalizer", 0, false);
 134                     sft.start();
 135                     try {
 136                         sft.join();
 137                     } catch (InterruptedException x) {
 138                         Thread.currentThread().interrupt();
 139                     }
 140                     return null;
 141                 }});
 142     }
 143 
 144     /* Called by Runtime.runFinalization() */
 145     static void runFinalization() {
 146         if (!VM.isBooted()) {
 147             return;
 148         }
 149 
 150         forkSecondaryFinalizer(new Runnable() {
 151             private volatile boolean running;
 152             public void run() {
 153                 // in case of recursive call to run()


 172 
 173         forkSecondaryFinalizer(new Runnable() {
 174             private volatile boolean running;
 175             public void run() {
 176                 // in case of recursive call to run()
 177                 if (running)
 178                     return;
 179                 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
 180                 running = true;
 181                 for (;;) {
 182                     Finalizer f;
 183                     synchronized (lock) {
 184                         f = unfinalized;
 185                         if (f == null) break;
 186                         unfinalized = f.next;
 187                     }
 188                     f.runFinalizer(jla);
 189                 }}});
 190     }
 191 
 192     private static class FinalizerThread extends Thread {
 193         private volatile boolean running;
 194         FinalizerThread(ThreadGroup g) {
 195             super(g, null, "Finalizer", 0, false);
 196         }
 197         public void run() {
 198             // in case of recursive call to run()
 199             if (running)
 200                 return;
 201 
 202             // Finalizer thread starts before System.initializeSystemClass
 203             // is called.  Wait until JavaLangAccess is available
 204             while (!VM.isBooted()) {
 205                 // delay until VM completes initialization
 206                 try {
 207                     VM.awaitBooted();
 208                 } catch (InterruptedException x) {
 209                     // ignore and continue
 210                 }
 211             }
 212             final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
 213             running = true;
 214             for (;;) {
 215                 try {