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