1 /*
   2  * Copyright (c) 2003, 2013, 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<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 
  83         // If already removed, do nothing
  84         if (cl.next == cl)
  85             return false;
  86 
  87         // Update list
  88         if (first == cl) {
  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 
 130     /**
 131      * Runs this cleaner, if it has not been run before.
 132      */
 133     public void clean() {
 134         if (!remove(this))
 135             return;
 136         try {
 137             thunk.run();
 138         } catch (final Throwable x) {
 139             AccessController.doPrivileged(new PrivilegedAction<>() {
 140                     public Void run() {
 141                         if (System.err != null)
 142                             new Error("Cleaner terminated abnormally", x)
 143                                 .printStackTrace();
 144                         System.exit(1);
 145                         return null;
 146                     }});
 147         }
 148     }
 149 
 150 }