src/java.base/share/classes/java/lang/ref/Finalizer.java
changeset 48942 a6c4b85163c1
parent 48903 d9fce53461a1
child 52427 3c6aa484536c
equal deleted inserted replaced
48941:4f11514fe783 48942:a6c4b85163c1
     1 /*
     1 /*
     2  * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    64     /* Invoked by VM */
    64     /* Invoked by VM */
    65     static void register(Object finalizee) {
    65     static void register(Object finalizee) {
    66         new Finalizer(finalizee);
    66         new Finalizer(finalizee);
    67     }
    67     }
    68 
    68 
    69     private void deregisterAndRunFinalizer(JavaLangAccess jla) {
    69     private void runFinalizer(JavaLangAccess jla) {
    70         synchronized (lock) {
    70         synchronized (lock) {
    71             if (this.next == this)      // already finalized
    71             if (this.next == this)      // already finalized
    72                 return;
    72                 return;
    73             // unlink from unfinalized
    73             // unlink from unfinalized
    74             if (unfinalized == this)
    74             if (unfinalized == this)
    78             if (this.next != null)
    78             if (this.next != null)
    79                 this.next.prev = this.prev;
    79                 this.next.prev = this.prev;
    80             this.prev = null;
    80             this.prev = null;
    81             this.next = this;           // mark as finalized
    81             this.next = this;           // mark as finalized
    82         }
    82         }
    83         runFinalizer(jla);
       
    84     }
       
    85 
    83 
    86     private void runFinalizer(JavaLangAccess jla) {
       
    87         try {
    84         try {
    88             Object finalizee = this.get();
    85             Object finalizee = this.get();
    89             if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
    86             if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
    90                 jla.invokeFinalize(finalizee);
    87                 jla.invokeFinalize(finalizee);
    91 
    88 
    92                 /* Clear stack slot containing this variable, to decrease
    89                 // Clear stack slot containing this variable, to decrease
    93                    the chances of false retention with a conservative GC */
    90                 // the chances of false retention with a conservative GC
    94                 finalizee = null;
    91                 finalizee = null;
    95             }
    92             }
    96         } catch (Throwable x) { }
    93         } catch (Throwable x) { }
    97         super.clear();
    94         super.clear();
    98     }
    95     }
    99 
    96 
   100     /* Create a privileged secondary finalizer thread in the system thread
    97     /* Create a privileged secondary finalizer thread in the system thread
   101        group for the given Runnable, and wait for it to complete.
    98      * group for the given Runnable, and wait for it to complete.
   102 
    99      *
   103        This method is used by both runFinalization and runFinalizersOnExit.
   100      * This method is used by runFinalization.
   104        The former method invokes all pending finalizers, while the latter
   101      *
   105        invokes all uninvoked finalizers if on-exit finalization has been
   102      * It could have been implemented by offloading the work to the
   106        enabled.
   103      * regular finalizer thread and waiting for that thread to finish.
   107 
   104      * The advantage of creating a fresh thread, however, is that it insulates
   108        These two methods could have been implemented by offloading their work
   105      * invokers of that method from a stalled or deadlocked finalizer thread.
   109        to the regular finalizer thread and waiting for that thread to finish.
       
   110        The advantage of creating a fresh thread, however, is that it insulates
       
   111        invokers of these methods from a stalled or deadlocked finalizer thread.
       
   112      */
   106      */
   113     private static void forkSecondaryFinalizer(final Runnable proc) {
   107     private static void forkSecondaryFinalizer(final Runnable proc) {
   114         AccessController.doPrivileged(
   108         AccessController.doPrivileged(
   115             new PrivilegedAction<>() {
   109             new PrivilegedAction<>() {
   116                 public Void run() {
   110                 public Void run() {
   142                 if (running)
   136                 if (running)
   143                     return;
   137                     return;
   144                 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
   138                 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
   145                 running = true;
   139                 running = true;
   146                 for (Finalizer f; (f = (Finalizer)queue.poll()) != null; )
   140                 for (Finalizer f; (f = (Finalizer)queue.poll()) != null; )
   147                     f.deregisterAndRunFinalizer(jla);
   141                     f.runFinalizer(jla);
   148             }
   142             }
   149         });
   143         });
   150     }
       
   151 
       
   152     /* Invoked by java.lang.Shutdown */
       
   153     static void runAllFinalizers() {
       
   154         if (VM.initLevel() == 0) {
       
   155             return;
       
   156         }
       
   157 
       
   158         forkSecondaryFinalizer(new Runnable() {
       
   159             private volatile boolean running;
       
   160             public void run() {
       
   161                 // in case of recursive call to run()
       
   162                 if (running)
       
   163                     return;
       
   164                 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
       
   165                 running = true;
       
   166                 for (;;) {
       
   167                     // "pollFirst" from unfinalized
       
   168                     Finalizer f;
       
   169                     synchronized (lock) {
       
   170                         f = unfinalized;
       
   171                         if (f == null) break;
       
   172                         unfinalized = f.next;
       
   173                         if (unfinalized != null)
       
   174                             unfinalized.prev = null;
       
   175                         f.next = f; // mark as finalized
       
   176                     }
       
   177                     f.runFinalizer(jla);
       
   178                 }}});
       
   179     }
   144     }
   180 
   145 
   181     private static class FinalizerThread extends Thread {
   146     private static class FinalizerThread extends Thread {
   182         private volatile boolean running;
   147         private volatile boolean running;
   183         FinalizerThread(ThreadGroup g) {
   148         FinalizerThread(ThreadGroup g) {
   201             final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
   166             final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
   202             running = true;
   167             running = true;
   203             for (;;) {
   168             for (;;) {
   204                 try {
   169                 try {
   205                     Finalizer f = (Finalizer)queue.remove();
   170                     Finalizer f = (Finalizer)queue.remove();
   206                     f.deregisterAndRunFinalizer(jla);
   171                     f.runFinalizer(jla);
   207                 } catch (InterruptedException x) {
   172                 } catch (InterruptedException x) {
   208                     // ignore and continue
   173                     // ignore and continue
   209                 }
   174                 }
   210             }
   175             }
   211         }
   176         }