UnreferencedContext.java revision 6244:bd84d0927a2e
1/* 2 * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* @test 25 * @bug 4171278 26 * @summary A remote object's unreferenced() method should be invoked with the 27 * context class loader set to the same context class loader that would be set 28 * when remote calls for that object are being executed: the object's class's 29 * class loader, or the context class loader set when the remote object was 30 * exported, if it is a child of the remote object's class loader. 31 * @author Peter Jones 32 * 33 * @bug 4214123 34 * @summary Unreferenced.unreferenced(...) threads should run in the nonSystem group. 35 * To complete the fix for, 4182104, RMI unreferenced threads should also 36 * run in the nonSystem so that they do not need permissions to modify the 37 * system thread group. 38 * 39 * @author Laird Dornin 40 * 41 * @library ../../../testlibrary 42 * @build TestLibrary UnreferencedContext_Stub 43 * @run main/othervm/timeout=120 UnreferencedContext 44 */ 45 46import java.net.*; 47import java.rmi.*; 48import java.rmi.registry.*; 49import java.rmi.server.*; 50 51public class UnreferencedContext implements Remote, Unreferenced, Runnable { 52 53 private final static String BINDING = "UnreferencedContext"; 54 private final static long GC_INTERVAL = 6000; 55 private final static long TIMEOUT = 60000; 56 57 private Object lock = new Object(); 58 private boolean unreferencedInvoked = false; 59 private ClassLoader unreferencedContext; 60 61 public void run() { 62 System.err.println("unreferenced method created thread succesfully"); 63 } 64 65 public void unreferenced() { 66 // turn on security to ensure that the action below will not 67 // require extra permissions 68 System.setSecurityManager(new java.rmi.RMISecurityManager()); 69 70 // exercise functionality prohibited by 4214123 71 (new Thread(this)).start(); 72 73 System.err.println("unreferenced() method invoked"); 74 synchronized (lock) { 75 unreferencedInvoked = true; 76 unreferencedContext = 77 Thread.currentThread().getContextClassLoader(); 78 lock.notify(); 79 } 80 } 81 82 public static void main(String[] args) { 83 84 System.err.println("\nRegression test for bug 4171278\n"); 85 86 /* 87 * Set the interval that RMI will request for GC latency (before RMI 88 * gets initialized and this property is read) to an unrealistically 89 * small value, so that this test shouldn't have to wait too long. 90 */ 91 System.setProperty("sun.rmi.dgc.client.gcInterval", 92 String.valueOf(GC_INTERVAL)); 93 94 UnreferencedContext obj = new UnreferencedContext(); 95 96 try { 97 /* 98 * This little trick is necessary to make sure that the RMI server 99 * threads for objects created on the default port get created 100 * before we set our special context class loader, so that they 101 * don't *accidentally* inherit it when making the unreferenced() 102 * callback. 103 */ 104 UnicastRemoteObject.exportObject(obj); 105 UnicastRemoteObject.unexportObject(obj, true); 106 107 /* 108 * Now create special context class loader before exporting the 109 * remote object for real, so that it should be set when the 110 * object's unreferenced() method is called. 111 */ 112 ClassLoader intendedContext = new URLClassLoader(new URL[0]); 113 Thread.currentThread().setContextClassLoader(intendedContext); 114 System.err.println( 115 "created and set intended context class loader: " + 116 intendedContext); 117 118 UnicastRemoteObject.exportObject(obj); 119 System.err.println("exported remote object"); 120 121 Registry registry1 = TestLibrary.createRegistryOnUnusedPort(); 122 int port = TestLibrary.getRegistryPort(registry1); 123 System.err.println("created registry"); 124 125 Registry registry = LocateRegistry.getRegistry("", port); 126 registry.bind(BINDING, obj); 127 System.err.println("bound remote object in registry"); 128 129 synchronized (obj.lock) { 130 registry.unbind(BINDING); 131 System.err.println("unbound remote object from registry; " + 132 "waiting for unreferenced() callback..."); 133 /* 134 * This incantation seems sufficient to work around the 135 * ramifications of 4164696, so that this test will actually 136 * prove something useful about 1.2Beta4 or 1.2FCS before 137 * 4171278 was fixed. 138 */ 139 for (int i = 0; i < 10; i++) { 140 System.gc(); 141 obj.lock.wait(TIMEOUT / 10); 142 if (obj.unreferencedInvoked) { 143 break; 144 } 145 } 146 147 if (obj.unreferencedInvoked) { 148 System.err.println( 149 "invoked with context class loader: " + 150 obj.unreferencedContext); 151 152 if (obj.unreferencedContext == intendedContext) { 153 System.err.println( 154 "TEST PASSED: unreferenced() invoked" + 155 " with intended context class loader"); 156 } else { 157 throw new RuntimeException( 158 "TEST FAILED: unreferenced() invoked" + 159 " with incorrect context class loader"); 160 } 161 } else { 162 throw new RuntimeException( 163 "TEST FAILED: unreferenced() not invoked after " + 164 ((double) TIMEOUT / 1000.0) + " seconds or unreferenced failed to create a thread"); 165 } 166 } 167 168 } catch (Exception e) { 169 if (e instanceof RuntimeException) { 170 throw (RuntimeException) e; 171 } else { 172 throw new RuntimeException( 173 "TEST FAILED: unexpected exception: " + e.toString()); 174 } 175 } finally { 176 /* 177 * When all is said and done, try to unexport the remote object 178 * so that the VM has a chance to exit. 179 */ 180 try { 181 UnicastRemoteObject.unexportObject(obj, true); 182 } catch (RemoteException e) { 183 } 184 } 185 } 186} 187