1ef39d40dSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3ef39d40dSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4ef39d40dSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5ef39d40dSAndrew Rist  * distributed with this work for additional information
6ef39d40dSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7ef39d40dSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8ef39d40dSAndrew Rist  * "License"); you may not use this file except in compliance
9ef39d40dSAndrew Rist  * with the License.  You may obtain a copy of the License at
10ef39d40dSAndrew Rist  *
11ef39d40dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12ef39d40dSAndrew Rist  *
13ef39d40dSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14ef39d40dSAndrew Rist  * software distributed under the License is distributed on an
15ef39d40dSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16ef39d40dSAndrew Rist  * KIND, either express or implied.  See the License for the
17ef39d40dSAndrew Rist  * specific language governing permissions and limitations
18ef39d40dSAndrew Rist  * under the License.
19ef39d40dSAndrew Rist  *
20ef39d40dSAndrew Rist  *************************************************************/
21ef39d40dSAndrew Rist 
22ef39d40dSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir package util;
25cdf0e10cSrcweir 
26cdf0e10cSrcweir import java.lang.ref.PhantomReference;
27cdf0e10cSrcweir import java.lang.ref.ReferenceQueue;
28cdf0e10cSrcweir 
29cdf0e10cSrcweir /**
30cdf0e10cSrcweir  * Wait until an object has become unreachable.
31cdf0e10cSrcweir  *
32cdf0e10cSrcweir  * <p>Instances of this class will typically be used as either:</p>
33cdf0e10cSrcweir  * <pre>
34cdf0e10cSrcweir  *   SomeType o = new SomeType(...);
35cdf0e10cSrcweir  *   ... // use "o"
36cdf0e10cSrcweir  *   WaitUnreachable u = new WaitUnreachable(o);
37cdf0e10cSrcweir  *   o = null;
38cdf0e10cSrcweir  *   u.waitUnreachable();
39cdf0e10cSrcweir  * </pre>
40cdf0e10cSrcweir  * <p>or:</p>
41cdf0e10cSrcweir  * <pre>
42cdf0e10cSrcweir  *   WaitUnreachable u = new WaitUnreachable(new SomeType(...));
43cdf0e10cSrcweir  *   ... // use "(SomeType) u.get()"
44cdf0e10cSrcweir  *   u.waitUnreachable();
45cdf0e10cSrcweir  * </pre>
46cdf0e10cSrcweir  */
47cdf0e10cSrcweir public final class WaitUnreachable {
48cdf0e10cSrcweir     /**
49cdf0e10cSrcweir      * Creates a new waiter.
50cdf0e10cSrcweir      *
51cdf0e10cSrcweir      * @param obj the object on which to wait
52cdf0e10cSrcweir      */
WaitUnreachable(Object obj)53cdf0e10cSrcweir     public WaitUnreachable(Object obj) {
54cdf0e10cSrcweir         this.obj = obj;
55cdf0e10cSrcweir         queue = new ReferenceQueue();
56cdf0e10cSrcweir         ref = new PhantomReference(obj, queue);
57cdf0e10cSrcweir     }
58cdf0e10cSrcweir 
59cdf0e10cSrcweir     /**
60cdf0e10cSrcweir      * Gets the object on which to wait.
61cdf0e10cSrcweir      *
62cdf0e10cSrcweir      * @return the object on which to wait, or <code>null</code> if
63cdf0e10cSrcweir      * <code>waitUnreachable</code> has already been called
64cdf0e10cSrcweir      */
get()65cdf0e10cSrcweir     public synchronized Object get() {
66cdf0e10cSrcweir         return obj;
67cdf0e10cSrcweir     }
68cdf0e10cSrcweir 
69cdf0e10cSrcweir     /**
70cdf0e10cSrcweir      * Starts waiting for the object to become unreachable.
71cdf0e10cSrcweir      *
72cdf0e10cSrcweir      * <p>This blocks the current thread until the object has become
73cdf0e10cSrcweir      * unreachable.</p>
74cdf0e10cSrcweir      *
75cdf0e10cSrcweir      * <p>Actually, this method waits until the JVM has <em>detected</em> that
76cdf0e10cSrcweir      * the object has become unreachable.  This is not deterministic, but this
77cdf0e10cSrcweir      * methods makes a best effort to cause the JVM to eventually detect the
78cdf0e10cSrcweir      * situation.  With a typical JVM, this should suffice.</p>
79cdf0e10cSrcweir      */
waitUnreachable()80cdf0e10cSrcweir     public void waitUnreachable() {
81cdf0e10cSrcweir         synchronized (this) {
82cdf0e10cSrcweir             obj = null;
83cdf0e10cSrcweir         }
84cdf0e10cSrcweir         System.out.println("waiting for gc");
85cdf0e10cSrcweir         while (queue.poll() == null) {
86cdf0e10cSrcweir             System.gc();
87cdf0e10cSrcweir             System.runFinalization();
88cdf0e10cSrcweir             byte[] dummy = new byte[1024];
89cdf0e10cSrcweir         }
90cdf0e10cSrcweir     }
91cdf0e10cSrcweir 
92cdf0e10cSrcweir     /**
93cdf0e10cSrcweir      * Ensures that an object will be finalized as soon as possible.
94cdf0e10cSrcweir      *
95cdf0e10cSrcweir      * <p>This does not block the current thread.  Instead, a new thread is
96cdf0e10cSrcweir      * spawned that busy waits for the given object to become unreachable.</p>
97cdf0e10cSrcweir      *
98cdf0e10cSrcweir      * <p>This method cannot guarantee that the given object is eventually
99cdf0e10cSrcweir      * finalized, but it makes a best effort.  With a typical JVM, this should
100cdf0e10cSrcweir      * suffice.</p>
101cdf0e10cSrcweir      *
102cdf0e10cSrcweir      * @param obj the object of which to ensure finalization
103cdf0e10cSrcweir      */
ensureFinalization(final Object obj)104cdf0e10cSrcweir     public static void ensureFinalization(final Object obj) {
105cdf0e10cSrcweir         final class WaitThread extends Thread {
106cdf0e10cSrcweir             public WaitThread(Object obj) {
107cdf0e10cSrcweir                 super("ensureFinalization");
108cdf0e10cSrcweir                 unreachable = new WaitUnreachable(obj);
109cdf0e10cSrcweir             }
110cdf0e10cSrcweir 
111cdf0e10cSrcweir             public void run() {
112cdf0e10cSrcweir                 unreachable.waitUnreachable();
113cdf0e10cSrcweir             }
114cdf0e10cSrcweir 
115cdf0e10cSrcweir             private final WaitUnreachable unreachable;
116*170fb961SPedro Giffuni         }
117cdf0e10cSrcweir         new WaitThread(obj).start();
118cdf0e10cSrcweir     }
119cdf0e10cSrcweir 
120cdf0e10cSrcweir     private Object obj;
121cdf0e10cSrcweir     private final ReferenceQueue queue;
122cdf0e10cSrcweir     private final PhantomReference ref;
123cdf0e10cSrcweir }
124