1 19 20 package org.openide.util; 21 22 import java.lang.ref.Reference ; 23 import java.lang.ref.ReferenceQueue ; 24 import java.lang.ref.WeakReference ; 25 import java.net.URL ; 26 import java.net.URLClassLoader ; 27 import org.netbeans.junit.NbTestCase; 28 29 public class UtilitiesActiveQueueTest extends NbTestCase { 30 31 public UtilitiesActiveQueueTest(String testName) { 32 super(testName); 33 } 34 35 public void testRunnableReferenceIsExecuted () throws Exception { 36 Object obj = new Object (); 37 RunnableRef ref = new RunnableRef (obj); 38 synchronized (ref) { 39 obj = null; 40 assertGC ("Should be GCed quickly", ref); 41 ref.wait (); 42 assertTrue ("Run method has been executed", ref.executed); 43 } 44 } 45 46 public void testRunnablesAreProcessedOneByOne () throws Exception { 47 Object obj = new Object (); 48 RunnableRef ref = new RunnableRef (obj); 49 ref.wait = true; 50 51 52 synchronized (ref) { 53 obj = null; 54 assertGC ("Is garbage collected", ref); 55 ref.wait (); 56 assertTrue ("Still not executed, it is blocked", !ref.executed); 57 } 58 59 RunnableRef after = new RunnableRef (new Object ()); 60 synchronized (after) { 61 assertGC ("Is garbage collected", after); 62 after.wait (100); assertTrue ("Even if GCed, still not processed", !after.executed); 64 } 65 66 synchronized (after) { 67 synchronized (ref) { 68 ref.notify (); 69 ref.wait (); 70 assertTrue ("Processed", ref.executed); 71 } 72 after.wait (); 73 assertTrue ("Processed too", after.executed); 74 } 75 } 76 77 public void testCallingPublicMethodsThrowsExceptions () { 78 try { 79 Utilities.activeReferenceQueue().poll(); 80 fail ("One should not call public method from outside"); 81 } catch (RuntimeException ex) { 82 } 83 try { 84 Utilities.activeReferenceQueue ().remove (); 85 fail ("One should not call public method from outside"); 86 } catch (InterruptedException ex) { 87 } 88 try { 89 Utilities.activeReferenceQueue ().remove (10); 90 fail ("One should not call public method from outside"); 91 } catch (InterruptedException ex) { 92 } 93 } 94 95 public void testMemoryLeak() throws Exception { 96 final Class <?> u1 = Utilities.class; 97 class L extends URLClassLoader { 98 public L() { 99 super(new URL [] {u1.getProtectionDomain().getCodeSource().getLocation()}, u1.getClassLoader().getParent()); 100 } 101 protected Class <?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 102 if (name.equals(u1.getName()) || name.startsWith(u1.getName() + "$")) { 103 Class c = findLoadedClass(name); 104 if (c == null) { 105 c = findClass(name); 106 } 107 if (resolve) { 108 resolveClass(c); 109 } 110 return c; 111 } else { 112 return super.loadClass(name, resolve); 113 } 114 } 115 } 116 ClassLoader l = new L (); 117 Class <?> u2 = l.loadClass(u1.getName()); 118 assertEquals(l, u2.getClassLoader()); 119 Object obj = new Object (); 120 @SuppressWarnings ("unchecked") 121 ReferenceQueue <Object > q = (ReferenceQueue <Object >) u2.getMethod("activeReferenceQueue").invoke(null); 122 RunnableRef ref = new RunnableRef(obj, q); 123 synchronized (ref) { 124 obj = null; 125 assertGC("Ref should be GC'ed as usual", ref); 126 ref.wait(); 127 assertTrue("Run method has been executed", ref.executed); 128 } 129 Reference <?> r = new WeakReference <Object >(u2); 130 q = null; 131 u2 = null; 132 l = null; 133 assertGC("#86625: Utilities.class can also be collected now", r); 134 } 135 136 137 private static class RunnableRef extends WeakReference <Object > 138 implements Runnable { 139 public boolean wait; 140 public boolean entered; 141 public boolean executed; 142 143 public RunnableRef (Object o) { 144 this(o, Utilities.activeReferenceQueue()); 145 } 146 147 public RunnableRef(Object o, ReferenceQueue <Object > q) { 148 super(o, q); 149 } 150 151 public synchronized void run () { 152 entered = true; 153 if (wait) { 154 notify (); 156 try { 157 wait (); 158 } catch (InterruptedException ex) { 159 } 160 } 161 executed = true; 162 163 notifyAll (); 164 } 165 } 166 } 167 | Popular Tags |