jdk/src/share/classes/java/lang/ref/Finalizer.java
changeset 21628 50fd58446d64
parent 19053 69648476a89e
equal deleted inserted replaced
21627:5e31d6573ec2 21628:50fd58446d64
    25 
    25 
    26 package java.lang.ref;
    26 package java.lang.ref;
    27 
    27 
    28 import java.security.PrivilegedAction;
    28 import java.security.PrivilegedAction;
    29 import java.security.AccessController;
    29 import java.security.AccessController;
    30 
    30 import sun.misc.JavaLangAccess;
       
    31 import sun.misc.SharedSecrets;
       
    32 import sun.misc.VM;
    31 
    33 
    32 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in
    34 final class Finalizer extends FinalReference<Object> { /* Package-private; must be in
    33                                                           same package as the Reference
    35                                                           same package as the Reference
    34                                                           class */
    36                                                           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 
    37 
    41     private static ReferenceQueue<Object> queue = new ReferenceQueue<>();
    38     private static ReferenceQueue<Object> queue = new ReferenceQueue<>();
    42     private static Finalizer unfinalized = null;
    39     private static Finalizer unfinalized = null;
    43     private static final Object lock = new Object();
    40     private static final Object lock = new Object();
    44 
    41 
    88     /* Invoked by VM */
    85     /* Invoked by VM */
    89     static void register(Object finalizee) {
    86     static void register(Object finalizee) {
    90         new Finalizer(finalizee);
    87         new Finalizer(finalizee);
    91     }
    88     }
    92 
    89 
    93     private void runFinalizer() {
    90     private void runFinalizer(JavaLangAccess jla) {
    94         synchronized (this) {
    91         synchronized (this) {
    95             if (hasBeenFinalized()) return;
    92             if (hasBeenFinalized()) return;
    96             remove();
    93             remove();
    97         }
    94         }
    98         try {
    95         try {
    99             Object finalizee = this.get();
    96             Object finalizee = this.get();
   100             if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
    97             if (finalizee != null && !(finalizee instanceof java.lang.Enum)) {
   101                 invokeFinalizeMethod(finalizee);
    98                 jla.invokeFinalize(finalizee);
       
    99 
   102                 /* Clear stack slot containing this variable, to decrease
   100                 /* Clear stack slot containing this variable, to decrease
   103                    the chances of false retention with a conservative GC */
   101                    the chances of false retention with a conservative GC */
   104                 finalizee = null;
   102                 finalizee = null;
   105             }
   103             }
   106         } catch (Throwable x) { }
   104         } catch (Throwable x) { }
   139                 }});
   137                 }});
   140     }
   138     }
   141 
   139 
   142     /* Called by Runtime.runFinalization() */
   140     /* Called by Runtime.runFinalization() */
   143     static void runFinalization() {
   141     static void runFinalization() {
       
   142         if (!VM.isBooted()) {
       
   143             return;
       
   144         }
       
   145 
   144         forkSecondaryFinalizer(new Runnable() {
   146         forkSecondaryFinalizer(new Runnable() {
   145             private volatile boolean running;
   147             private volatile boolean running;
   146             public void run() {
   148             public void run() {
   147                 if (running)
   149                 if (running)
   148                     return;
   150                     return;
       
   151                 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
   149                 running = true;
   152                 running = true;
   150                 for (;;) {
   153                 for (;;) {
   151                     Finalizer f = (Finalizer)queue.poll();
   154                     Finalizer f = (Finalizer)queue.poll();
   152                     if (f == null) break;
   155                     if (f == null) break;
   153                     f.runFinalizer();
   156                     f.runFinalizer(jla);
   154                 }
   157                 }
   155             }
   158             }
   156         });
   159         });
   157     }
   160     }
   158 
   161 
   159     /* Invoked by java.lang.Shutdown */
   162     /* Invoked by java.lang.Shutdown */
   160     static void runAllFinalizers() {
   163     static void runAllFinalizers() {
       
   164         if (!VM.isBooted()) {
       
   165             return;
       
   166         }
       
   167 
   161         forkSecondaryFinalizer(new Runnable() {
   168         forkSecondaryFinalizer(new Runnable() {
   162             private volatile boolean running;
   169             private volatile boolean running;
   163             public void run() {
   170             public void run() {
   164                 if (running)
   171                 if (running)
   165                     return;
   172                     return;
       
   173                 final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
   166                 running = true;
   174                 running = true;
   167                 for (;;) {
   175                 for (;;) {
   168                     Finalizer f;
   176                     Finalizer f;
   169                     synchronized (lock) {
   177                     synchronized (lock) {
   170                         f = unfinalized;
   178                         f = unfinalized;
   171                         if (f == null) break;
   179                         if (f == null) break;
   172                         unfinalized = f.next;
   180                         unfinalized = f.next;
   173                     }
   181                     }
   174                     f.runFinalizer();
   182                     f.runFinalizer(jla);
   175                 }}});
   183                 }}});
   176     }
   184     }
   177 
   185 
   178     private static class FinalizerThread extends Thread {
   186     private static class FinalizerThread extends Thread {
   179         private volatile boolean running;
   187         private volatile boolean running;
   181             super(g, "Finalizer");
   189             super(g, "Finalizer");
   182         }
   190         }
   183         public void run() {
   191         public void run() {
   184             if (running)
   192             if (running)
   185                 return;
   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();
   186             running = true;
   206             running = true;
   187             for (;;) {
   207             for (;;) {
   188                 try {
   208                 try {
   189                     Finalizer f = (Finalizer)queue.remove();
   209                     Finalizer f = (Finalizer)queue.remove();
   190                     f.runFinalizer();
   210                     f.runFinalizer(jla);
   191                 } catch (InterruptedException x) {
   211                 } catch (InterruptedException x) {
   192                     continue;
   212                     // ignore and continue
   193                 }
   213                 }
   194             }
   214             }
   195         }
   215         }
   196     }
   216     }
   197 
   217