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 * @modules java.rmi/sun.rmi.registry 43 * java.rmi/sun.rmi.server 44 * java.rmi/sun.rmi.transport 45 * java.rmi/sun.rmi.transport.tcp 46 * @build TestLibrary UnreferencedContext_Stub 47 * @run main/othervm/timeout=120 UnreferencedContext 48 */ 49 50 import java.net.*; 51 import java.rmi.*; 52 import java.rmi.registry.*; 53 import java.rmi.server.*; 54 55 public class UnreferencedContext implements Remote, Unreferenced, Runnable { 56 57 private final static String BINDING = "UnreferencedContext"; 58 private final static long GC_INTERVAL = 6000; 59 private final static long TIMEOUT = 60000; 60 61 private Object lock = new Object(); 62 private boolean unreferencedInvoked = false; 63 private ClassLoader unreferencedContext; 64 65 public void run() { 66 System.err.println("unreferenced method created thread succesfully"); 67 } 68 69 public void unreferenced() { 70 // turn on security to ensure that the action below will not 71 // require extra permissions 72 System.setSecurityManager(new java.rmi.RMISecurityManager()); 73 74 // exercise functionality prohibited by 4214123 75 (new Thread(this)).start(); 76 77 System.err.println("unreferenced() method invoked"); 78 synchronized (lock) { 79 unreferencedInvoked = true; 80 unreferencedContext = 81 Thread.currentThread().getContextClassLoader(); 82 lock.notify(); 83 } 84 } 85 86 public static void main(String[] args) { 87 88 System.err.println("\nRegression test for bug 4171278\n"); 89 90 /* 91 * Set the interval that RMI will request for GC latency (before RMI 92 * gets initialized and this property is read) to an unrealistically 93 * small value, so that this test shouldn't have to wait too long. 94 */ 95 System.setProperty("sun.rmi.dgc.client.gcInterval", 96 String.valueOf(GC_INTERVAL)); 97 98 UnreferencedContext obj = new UnreferencedContext(); 99 100 try { 101 /* 102 * This little trick is necessary to make sure that the RMI server 103 * threads for objects created on the default port get created 104 * before we set our special context class loader, so that they 105 * don't *accidentally* inherit it when making the unreferenced() 106 * callback. 107 */ 108 UnicastRemoteObject.exportObject(obj); 109 UnicastRemoteObject.unexportObject(obj, true); 110 111 /* 112 * Now create special context class loader before exporting the 113 * remote object for real, so that it should be set when the 114 * object's unreferenced() method is called. 115 */ 116 ClassLoader intendedContext = new URLClassLoader(new URL[0]); 117 Thread.currentThread().setContextClassLoader(intendedContext); 118 System.err.println( 119 "created and set intended context class loader: " + 120 intendedContext); 121 122 UnicastRemoteObject.exportObject(obj); 123 System.err.println("exported remote object"); 124 125 Registry registry1 = TestLibrary.createRegistryOnUnusedPort(); 126 int port = TestLibrary.getRegistryPort(registry1); 127 System.err.println("created registry"); 128 129 Registry registry = LocateRegistry.getRegistry("", port); 130 registry.bind(BINDING, obj); 131 System.err.println("bound remote object in registry"); 132 133 synchronized (obj.lock) { 134 registry.unbind(BINDING); 135 System.err.println("unbound remote object from registry; " + 136 "waiting for unreferenced() callback..."); 137 /* 138 * This incantation seems sufficient to work around the 139 * ramifications of 4164696, so that this test will actually 140 * prove something useful about 1.2Beta4 or 1.2FCS before 141 * 4171278 was fixed. 142 */ 143 for (int i = 0; i < 10; i++) { 144 System.gc(); 145 obj.lock.wait(TIMEOUT / 10); 146 if (obj.unreferencedInvoked) { 147 break; 148 } 149 } 150 151 if (obj.unreferencedInvoked) { 152 System.err.println( 153 "invoked with context class loader: " + 154 obj.unreferencedContext); 155 156 if (obj.unreferencedContext == intendedContext) { 157 System.err.println( 158 "TEST PASSED: unreferenced() invoked" + 159 " with intended context class loader"); 160 } else { 161 throw new RuntimeException( 162 "TEST FAILED: unreferenced() invoked" + 163 " with incorrect context class loader"); 164 } 165 } else { 166 throw new RuntimeException( 167 "TEST FAILED: unreferenced() not invoked after " + 168 ((double) TIMEOUT / 1000.0) + " seconds or unreferenced failed to create a thread"); 169 } 170 } 171 172 } catch (Exception e) { 173 if (e instanceof RuntimeException) { 174 throw (RuntimeException) e; 175 } else { 176 throw new RuntimeException( 177 "TEST FAILED: unexpected exception: " + e.toString()); 178 } 179 } finally { 180 /* 181 * When all is said and done, try to unexport the remote object 182 * so that the VM has a chance to exit. 183 */ 184 try { 185 UnicastRemoteObject.unexportObject(obj, true); 186 } catch (RemoteException e) { 187 } 188 } 189 } 190 }