1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 package util; 29 30 import java.lang.ref.PhantomReference; 31 import java.lang.ref.ReferenceQueue; 32 33 /** 34 * Wait until an object has become unreachable. 35 * 36 * <p>Instances of this class will typically be used as either:</p> 37 * <pre> 38 * SomeType o = new SomeType(...); 39 * ... // use "o" 40 * WaitUnreachable u = new WaitUnreachable(o); 41 * o = null; 42 * u.waitUnreachable(); 43 * </pre> 44 * <p>or:</p> 45 * <pre> 46 * WaitUnreachable u = new WaitUnreachable(new SomeType(...)); 47 * ... // use "(SomeType) u.get()" 48 * u.waitUnreachable(); 49 * </pre> 50 */ 51 public final class WaitUnreachable { 52 /** 53 * Creates a new waiter. 54 * 55 * @param obj the object on which to wait 56 */ 57 public WaitUnreachable(Object obj) { 58 this.obj = obj; 59 queue = new ReferenceQueue(); 60 ref = new PhantomReference(obj, queue); 61 } 62 63 /** 64 * Gets the object on which to wait. 65 * 66 * @return the object on which to wait, or <code>null</code> if 67 * <code>waitUnreachable</code> has already been called 68 */ 69 public synchronized Object get() { 70 return obj; 71 } 72 73 /** 74 * Starts waiting for the object to become unreachable. 75 * 76 * <p>This blocks the current thread until the object has become 77 * unreachable.</p> 78 * 79 * <p>Actually, this method waits until the JVM has <em>detected</em> that 80 * the object has become unreachable. This is not deterministic, but this 81 * methods makes a best effort to cause the JVM to eventually detect the 82 * situation. With a typical JVM, this should suffice.</p> 83 */ 84 public void waitUnreachable() { 85 synchronized (this) { 86 obj = null; 87 } 88 System.out.println("waiting for gc"); 89 while (queue.poll() == null) { 90 System.gc(); 91 System.runFinalization(); 92 byte[] dummy = new byte[1024]; 93 } 94 } 95 96 /** 97 * Ensures that an object will be finalized as soon as possible. 98 * 99 * <p>This does not block the current thread. Instead, a new thread is 100 * spawned that busy waits for the given object to become unreachable.</p> 101 * 102 * <p>This method cannot guarantee that the given object is eventually 103 * finalized, but it makes a best effort. With a typical JVM, this should 104 * suffice.</p> 105 * 106 * @param obj the object of which to ensure finalization 107 */ 108 public static void ensureFinalization(final Object obj) { 109 final class WaitThread extends Thread { 110 public WaitThread(Object obj) { 111 super("ensureFinalization"); 112 unreachable = new WaitUnreachable(obj); 113 } 114 115 public void run() { 116 unreachable.waitUnreachable(); 117 } 118 119 private final WaitUnreachable unreachable; 120 }; 121 new WaitThread(obj).start(); 122 } 123 124 private Object obj; 125 private final ReferenceQueue queue; 126 private final PhantomReference ref; 127 } 128