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