< prev index next >

src/java.base/share/classes/sun/misc/Cleaner.java

Print this page




  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<Object>
  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<Object> 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 


  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  ob the referent object to be cleaned
 123      * @param  thunk
 124      *         The cleanup code to be run when the cleaner is invoked.  The
 125      *         cleanup code is run directly from the reference-handler thread,
 126      *         so it should be as simple and straightforward as possible.
 127      *
 128      * @return  The new cleaner
 129      */
 130     public static Cleaner create(Object ob, Runnable thunk) {
 131         if (thunk == null)
 132             return null;
 133         return add(new Cleaner(ob, thunk));
 134     }
 135 




  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<Object>
  61 {
  62 






  63     // Doubly-linked list of live cleaners, which prevents the cleaners
  64     // themselves from being GC'd before their referents
  65     //
  66     static private Cleaner first = null;
  67 
  68     private Cleaner
  69         next = null,
  70         prev = null;
  71 
  72     private static synchronized Cleaner add(Cleaner cl) {
  73         if (first != null) {
  74             cl.next = first;
  75             first.prev = cl;
  76         }
  77         first = cl;
  78         return cl;
  79     }
  80 
  81     private static synchronized boolean remove(Cleaner cl) {
  82 


  89             if (cl.next != null)
  90                 first = cl.next;
  91             else
  92                 first = cl.prev;
  93         }
  94         if (cl.next != null)
  95             cl.next.prev = cl.prev;
  96         if (cl.prev != null)
  97             cl.prev.next = cl.next;
  98 
  99         // Indicate removal by pointing the cleaner to itself
 100         cl.next = cl;
 101         cl.prev = cl;
 102         return true;
 103 
 104     }
 105 
 106     private final Runnable thunk;
 107 
 108     private Cleaner(Object referent, Runnable thunk) {
 109         super(referent, null);
 110         this.thunk = thunk;
 111     }
 112 
 113     /**
 114      * Creates a new cleaner.
 115      *
 116      * @param  ob the referent object to be cleaned
 117      * @param  thunk
 118      *         The cleanup code to be run when the cleaner is invoked.  The
 119      *         cleanup code is run directly from the reference-handler thread,
 120      *         so it should be as simple and straightforward as possible.
 121      *
 122      * @return  The new cleaner
 123      */
 124     public static Cleaner create(Object ob, Runnable thunk) {
 125         if (thunk == null)
 126             return null;
 127         return add(new Cleaner(ob, thunk));
 128     }
 129 


< prev index next >