Save This Page
Home » openjdk-7 » sun » misc » [javadoc | source]
    1   /*
    2    * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    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
    7    * published by the Free Software Foundation.  Oracle designates this
    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 sun.misc;
   27   
   28   import java.lang.ref;
   29   import java.security.AccessController;
   30   import java.security.PrivilegedAction;
   31   
   32   
   33   /**
   34    * General-purpose phantom-reference-based cleaners.
   35    *
   36    * <p> Cleaners are a lightweight and more robust alternative to finalization.
   37    * They are lightweight because they are not created by the VM and thus do not
   38    * require a JNI upcall to be created, and because their cleanup code is
   39    * invoked directly by the reference-handler thread rather than by the
   40    * finalizer thread.  They are more robust because they use phantom references,
   41    * the weakest type of reference object, thereby avoiding the nasty ordering
   42    * problems inherent to finalization.
   43    *
   44    * <p> A cleaner tracks a referent object and encapsulates a thunk of arbitrary
   45    * cleanup code.  Some time after the GC detects that a cleaner's referent has
   46    * become phantom-reachable, the reference-handler thread will run the cleaner.
   47    * Cleaners may also be invoked directly; they are thread safe and ensure that
   48    * they run their thunks at most once.
   49    *
   50    * <p> Cleaners are not a replacement for finalization.  They should be used
   51    * only when the cleanup code is extremely simple and straightforward.
   52    * Nontrivial cleaners are inadvisable since they risk blocking the
   53    * reference-handler thread and delaying further cleanup and finalization.
   54    *
   55    *
   56    * @author Mark Reinhold
   57    */
   58   
   59   public class Cleaner
   60       extends PhantomReference
   61   {
   62   
   63       // Dummy reference queue, needed because the PhantomReference constructor
   64       // insists that we pass a queue.  Nothing will ever be placed on this queue
   65       // since the reference handler invokes cleaners explicitly.
   66       //
   67       private static final ReferenceQueue dummyQueue = new ReferenceQueue();
   68   
   69       // Doubly-linked list of live cleaners, which prevents the cleaners
   70       // themselves from being GC'd before their referents
   71       //
   72       static private Cleaner first = null;
   73   
   74       private Cleaner
   75           next = null,
   76           prev = null;
   77   
   78       private static synchronized Cleaner add(Cleaner cl) {
   79           if (first != null) {
   80               cl.next = first;
   81               first.prev = cl;
   82           }
   83           first = cl;
   84           return cl;
   85       }
   86   
   87       private static synchronized boolean remove(Cleaner cl) {
   88   
   89           // If already removed, do nothing
   90           if (cl.next == cl)
   91               return false;
   92   
   93           // Update list
   94           if (first == cl) {
   95               if (cl.next != null)
   96                   first = cl.next;
   97               else
   98                   first = cl.prev;
   99           }
  100           if (cl.next != null)
  101               cl.next.prev = cl.prev;
  102           if (cl.prev != null)
  103               cl.prev.next = cl.next;
  104   
  105           // Indicate removal by pointing the cleaner to itself
  106           cl.next = cl;
  107           cl.prev = cl;
  108           return true;
  109   
  110       }
  111   
  112       private final Runnable thunk;
  113   
  114       private Cleaner(Object referent, Runnable thunk) {
  115           super(referent, dummyQueue);
  116           this.thunk = thunk;
  117       }
  118   
  119       /**
  120        * Creates a new cleaner.
  121        *
  122        * @param  thunk
  123        *         The cleanup code to be run when the cleaner is invoked.  The
  124        *         cleanup code is run directly from the reference-handler thread,
  125        *         so it should be as simple and straightforward as possible.
  126        *
  127        * @return  The new cleaner
  128        */
  129       public static Cleaner create(Object ob, Runnable thunk) {
  130           if (thunk == null)
  131               return null;
  132           return add(new Cleaner(ob, thunk));
  133       }
  134   
  135       /**
  136        * Runs this cleaner, if it has not been run before.
  137        */
  138       public void clean() {
  139           if (!remove(this))
  140               return;
  141           try {
  142               thunk.run();
  143           } catch (final Throwable x) {
  144               AccessController.doPrivileged(new PrivilegedAction<Void>() {
  145                       public Void run() {
  146                           if (System.err != null)
  147                               new Error("Cleaner terminated abnormally", x)
  148                                   .printStackTrace();
  149                           System.exit(1);
  150                           return null;
  151                       }});
  152           }
  153       }
  154   
  155   }

Save This Page
Home » openjdk-7 » sun » misc » [javadoc | source]