1 /* 2 * Copyright (c) 2016, 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 /** 25 * @test 26 * @summary Basic test for redefineModule 27 * @modules java.instrument 28 * @build java.base/java.lang.TestProvider 29 * java.base/jdk.internal.test.TestProviderImpl1 30 * java.base/jdk.internal.test.TestProviderImpl2 31 * @run shell MakeJAR3.sh RedefineModuleAgent 32 * @run testng/othervm -javaagent:RedefineModuleAgent.jar RedefineModuleTest 33 */ 34 35 import java.lang.TestProvider; 36 import java.lang.instrument.Instrumentation; 37 import java.lang.reflect.Layer; 38 import java.lang.reflect.Module; 39 import java.net.URLStreamHandler; 40 import java.net.spi.URLStreamHandlerProvider; 41 import java.nio.file.FileSystems; 42 import java.util.ArrayList; 43 import java.util.Collection; 44 import java.util.HashMap; 45 import java.util.HashSet; 46 import java.util.List; 47 import java.util.Map; 48 import java.util.ServiceLoader; 49 import java.util.Set; 50 51 import org.testng.annotations.Test; 52 import static org.testng.Assert.*; 53 54 @Test 55 public class RedefineModuleTest { 56 57 static void redefineModule(Module module, 58 Set<Module> extraReads, 59 Map<String, Set<Module>> extraExports, 60 Map<String, Set<Module>> extraOpens, 61 Set<Class<?>> extraUses, 62 Map<Class<?>, List<Class<?>>> extraProvides) { 63 RedefineModuleAgent.redefineModule(module, 64 extraReads, 65 extraExports, 66 extraOpens, 67 extraUses, 68 extraProvides); 69 } 70 71 72 /** 73 * Use redefineModule to update java.base to read java.instrument 74 */ 75 public void testAddReads() { 76 Module baseModule = Object.class.getModule(); 77 Module instrumentModule = Instrumentation.class.getModule(); 78 79 // pre-conditions 80 assertFalse(baseModule.canRead(instrumentModule)); 81 82 // update java.base to read java.instrument 83 Set<Module> extraReads = Set.of(instrumentModule); 84 redefineModule(baseModule, extraReads, Map.of(), Map.of(), Set.of(), Map.of()); 85 assertTrue(baseModule.canRead(instrumentModule)); 86 } 87 88 /** 89 * Use redefineModule to update java.base to export jdk.internal.misc 90 */ 91 public void testAddExports() { 92 Module baseModule = Object.class.getModule(); 93 Module thisModule = this.getClass().getClassLoader().getUnnamedModule(); 94 String pkg = "jdk.internal.misc"; 95 96 // pre-conditions 97 assertFalse(baseModule.isExported(pkg)); 98 assertFalse(baseModule.isExported(pkg, thisModule)); 99 100 // update java.base to export jdk.internal.misc to an unnamed module 101 Map<String, Set<Module>> extraExports = Map.of(pkg, Set.of(thisModule)); 102 redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of()); 103 assertFalse(baseModule.isExported(pkg)); 104 assertTrue(baseModule.isExported(pkg, thisModule)); 105 assertFalse(baseModule.isOpen(pkg)); 106 assertFalse(baseModule.isOpen(pkg, thisModule)); 107 } 108 109 /** 110 * Use redefineModule to update java.base to open jdk.internal.loader 111 */ 112 public void testAddOpens() { 113 Module baseModule = Object.class.getModule(); 114 Module thisModule = this.getClass().getClassLoader().getUnnamedModule(); 115 String pkg = "jdk.internal.loader"; 116 117 // pre-conditions 118 assertFalse(baseModule.isOpen(pkg)); 119 assertFalse(baseModule.isOpen(pkg, thisModule)); 120 121 // update java.base to open dk.internal.loader to an unnamed module 122 Map<String, Set<Module>> extraExports = Map.of(pkg, Set.of(thisModule)); 123 redefineModule(baseModule, Set.of(), Map.of(), extraExports, Set.of(), Map.of()); 124 assertFalse(baseModule.isExported(pkg)); 125 assertTrue(baseModule.isExported(pkg, thisModule)); 126 assertFalse(baseModule.isOpen(pkg)); 127 assertTrue(baseModule.isOpen(pkg, thisModule)); 128 } 129 130 /** 131 * Use redefineModule to update java.base to use TestProvider and 132 * provide implementations of TestProvider. 133 */ 134 public void testAddUsesAndProvides() throws Exception { 135 Module baseModule = Object.class.getModule(); 136 Class<TestProvider> service = TestProvider.class; 137 138 // pre-conditions 139 assertFalse(baseModule.canUse(service)); 140 assertTrue(collect(ServiceLoader.load(service)).isEmpty()); 141 assertTrue(collect(ServiceLoader.load(Layer.boot(), service)).isEmpty()); 142 143 // update java.base to use TestProvider 144 redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(service), Map.of()); 145 assertTrue(baseModule.canUse(service)); 146 assertTrue(collect(ServiceLoader.load(service)).isEmpty()); 147 assertTrue(collect(ServiceLoader.load(Layer.boot(), service)).isEmpty()); 148 149 // update java.base to provide an implementation of TestProvider 150 Class<?> type1 = Class.forName("jdk.internal.test.TestProviderImpl1"); 151 Map<Class<?>, List<Class<?>>> extraProvides = Map.of(service, List.of(type1)); 152 redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides); 153 154 // invoke ServiceLoader from java.base to find providers 155 Set<TestProvider> providers = collect(TestProvider.providers()); 156 assertTrue(providers.size() == 1); 157 assertTrue(containsInstanceOf(providers, type1)); 158 159 // use ServiceLoader to load implementations visible via TCCL 160 providers = collect(ServiceLoader.load(service)); 161 assertTrue(collect(providers).size() == 1); 162 assertTrue(containsInstanceOf(collect(providers), type1)); 163 164 // use ServiceLoader to load implementations in the boot layer 165 providers = collect(ServiceLoader.load(Layer.boot(), service)); 166 assertTrue(collect(providers).size() == 1); 167 assertTrue(containsInstanceOf(collect(providers), type1)); 168 169 // update java.base to provide a second implementation of TestProvider 170 Class<?> type2 = Class.forName("jdk.internal.test.TestProviderImpl2"); 171 extraProvides = Map.of(service, List.of(type2)); 172 redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides); 173 174 // invoke ServiceLoader from java.base to find providers 175 providers = collect(TestProvider.providers()); 176 assertTrue(providers.size() == 2); 177 assertTrue(containsInstanceOf(providers, type1)); 178 assertTrue(containsInstanceOf(providers, type2)); 179 180 // use ServiceLoader to load implementations visible via TCCL 181 providers = collect(ServiceLoader.load(service)); 182 assertTrue(collect(providers).size() == 2); 183 assertTrue(containsInstanceOf(providers, type1)); 184 assertTrue(containsInstanceOf(providers, type2)); 185 186 // use ServiceLoader to load implementations in the boot layer 187 providers = collect(ServiceLoader.load(Layer.boot(), service)); 188 assertTrue(collect(providers).size() == 2); 189 assertTrue(containsInstanceOf(providers, type1)); 190 assertTrue(containsInstanceOf(providers, type2)); 191 } 192 193 private <S> Set<S> collect(Iterable<S> sl) { 194 Set<S> providers = new HashSet<>(); 195 sl.forEach(providers::add); 196 return providers; 197 } 198 199 private boolean containsInstanceOf(Collection<?> c, Class<?> type) { 200 for (Object o : c) { 201 if (type.isInstance(o)) return true; 202 } 203 return false; 204 } 205 206 @Test(expectedExceptions = IllegalArgumentException.class) 207 public void testExportPackageToEmptySet() { 208 // attempt to update java.base to export jdk.internal.misc to nobody 209 Module baseModule = Object.class.getModule(); 210 Map<String, Set<Module>> extraExports = Map.of("jdk.internal.misc", Set.of()); 211 redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of()); 212 } 213 214 @Test(expectedExceptions = IllegalArgumentException.class) 215 public void testOpenPackageToEmptySet() { 216 // attempt to update java.base to open jdk.internal.misc to nobody 217 Module baseModule = Object.class.getModule(); 218 Map<String, Set<Module>> extraOpens = Map.of("jdk.internal.misc", Set.of()); 219 redefineModule(baseModule, Set.of(), Map.of(), extraOpens, Set.of(), Map.of()); 220 } 221 222 @Test(expectedExceptions = IllegalArgumentException.class) 223 public void testProvideServiceWithEmptyList() throws Exception { 224 // update java.base to provide an empty list of TestProvider 225 Module baseModule = Object.class.getModule(); 226 Class<?> service = TestProvider.class; 227 Map<Class<?>, List<Class<?>>> extraProvides = Map.of(service, List.of()); 228 redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides); 229 } 230 231 /** 232 * Test redefineClass by attempting to update java.base to export a package 233 * that it does not contain. 234 */ 235 @Test(expectedExceptions = IllegalArgumentException.class) 236 public void testExportPackageNotInModule() { 237 Module baseModule = Object.class.getModule(); 238 String pkg = "jdk.doesnotexist"; 239 240 // attempt to update java.base to export jdk.doesnotexist 241 Map<String, Set<Module>> extraExports = Map.of(pkg, Set.of()); 242 redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of()); 243 } 244 245 /** 246 * Test redefineClass by attempting to update java.base to provide a service 247 * where the service provider class is not in the module. 248 */ 249 @Test(expectedExceptions = IllegalArgumentException.class) 250 public void testProvideServiceNotInModule() { 251 Module baseModule = Object.class.getModule(); 252 class MyProvider extends URLStreamHandlerProvider { 253 @Override 254 public URLStreamHandler createURLStreamHandler(String protocol) { 255 return null; 256 } 257 } 258 259 // attempt to update java.base to provide MyProvider 260 Map<Class<?>, List<Class<?>>> extraProvides 261 = Map.of(URLStreamHandlerProvider.class, List.of(MyProvider.class)); 262 redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides); 263 } 264 265 /** 266 * Test redefineClass by attempting to update java.base to provide a 267 * service where the service provider class is not a sub-type. 268 */ 269 @Test(expectedExceptions = IllegalArgumentException.class) 270 public void testProvideServiceNotSubtype() { 271 Module baseModule = Object.class.getModule(); 272 273 Class<?> service = TestProvider.class; 274 Class<?> impl = FileSystems.getDefault().provider().getClass(); 275 276 // attempt to update java.base to provide an implementation of TestProvider 277 Map<Class<?>, List<Class<?>>> extraProvides = Map.of(service, List.of(impl)); 278 redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides); 279 } 280 281 /** 282 * Test redefineClass with null 283 */ 284 public void testNulls() { 285 Module baseModule = Object.class.getModule(); 286 287 try { 288 redefineModule(null, Set.of(), Map.of(), Map.of(), Set.of(), Map.of()); 289 assertTrue(false); 290 } catch (NullPointerException e) { } 291 292 try { 293 redefineModule(baseModule, null, Map.of(), Map.of(), Set.of(), Map.of()); 294 assertTrue(false); 295 } catch (NullPointerException e) { } 296 297 try { 298 redefineModule(baseModule, Set.of(), null, Map.of(), Set.of(), Map.of()); 299 assertTrue(false); 300 } catch (NullPointerException e) { } 301 302 try { 303 redefineModule(baseModule, Set.of(), Map.of(), null, Set.of(), Map.of()); 304 assertTrue(false); 305 } catch (NullPointerException e) { } 306 307 try { 308 redefineModule(baseModule, Set.of(), Map.of(), Map.of(), null, Map.of()); 309 assertTrue(false); 310 } catch (NullPointerException e) { } 311 312 try { 313 redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), null); 314 assertTrue(false); 315 } catch (NullPointerException e) { } 316 317 try { 318 Set<Module> containsNull = new HashSet<>(); 319 containsNull.add(null); 320 redefineModule(baseModule, containsNull, Map.of(), Map.of(), Set.of(), Map.of()); 321 assertTrue(false); 322 } catch (NullPointerException e) { } 323 324 try { 325 Map<String, Set<Module>> extraExports = new HashMap<>(); 326 extraExports.put(null, Set.of()); 327 redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of()); 328 assertTrue(false); 329 } catch (NullPointerException e) { } 330 331 try { 332 Map<String, Set<Module>> extraExports = new HashMap<>(); 333 extraExports.put(null, Set.of()); 334 redefineModule(baseModule, Set.of(), Map.of(), extraExports, Set.of(), Map.of()); 335 assertTrue(false); 336 } catch (NullPointerException e) { } 337 338 try { 339 Set<Module> containsNull = new HashSet<>(); 340 containsNull.add(null); 341 Map<String, Set<Module>> extraExports = Map.of("java.lang", containsNull); 342 redefineModule(baseModule, Set.of(), extraExports, Map.of(), Set.of(), Map.of()); 343 assertTrue(false); 344 } catch (NullPointerException e) { } 345 346 try { 347 Set<Class<?>> containsNull = new HashSet<>(); 348 containsNull.add(null); 349 redefineModule(baseModule, Set.of(), Map.of(), Map.of(), containsNull, Map.of()); 350 assertTrue(false); 351 } catch (NullPointerException e) { } 352 353 try { 354 Map<Class<?>, List<Class<?>>> extraProvides = new HashMap<>(); 355 extraProvides.put(null, List.of()); 356 redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides); 357 assertTrue(false); 358 } catch (NullPointerException e) { } 359 360 try { 361 List<Class<?>> containsNull = new ArrayList<>(); 362 containsNull.add(null); 363 Map<Class<?>, List<Class<?>>> extraProvides = Map.of(TestProvider.class, containsNull); 364 redefineModule(baseModule, Set.of(), Map.of(), Map.of(), Set.of(), extraProvides); 365 assertTrue(false); 366 } catch (NullPointerException e) { } 367 } 368 369 }