1 /* 2 * Copyright (c) 2014, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.reflect; 27 28 import java.lang.module.Configuration; 29 import java.lang.module.ModuleDescriptor; 30 import java.lang.module.ResolvedModule; 31 import java.util.Collections; 32 import java.util.HashMap; 33 import java.util.HashSet; 34 import java.util.Map; 35 import java.util.Objects; 36 import java.util.Optional; 37 import java.util.Set; 38 import java.util.function.Function; 39 import java.util.stream.Collectors; 40 41 import jdk.internal.loader.Loader; 42 import jdk.internal.loader.LoaderPool; 43 import jdk.internal.misc.SharedSecrets; 44 import sun.security.util.SecurityConstants; 45 46 47 /** 48 * A layer of modules in the Java virtual machine. 49 * 50 * <p> A layer is created from a graph of modules that is the {@link 51 * Configuration} and a function that maps each module to a {@link ClassLoader}. 52 * Creating a layer informs the Java virtual machine about the classes that 53 * may be loaded from modules so that the Java virtual machine knows which 54 * module that each class is a member of. Each layer, except the {@link 55 * #empty() empty} layer, has a {@link #parent() parent}. </p> 56 * 57 * <p> Creating a layer creates a {@link Module} object for each {@link 58 * ResolvedModule} in the configuration. For each resolved module that is 59 * {@link ResolvedModule#reads() read}, the {@code Module} {@link 60 * Module#canRead reads} the corresponding run-time {@code Module}, which may 61 * be in the same layer or a parent layer. The {@code Module} {@link 62 * Module#isExported(String) exports} the packages described by its {@link 63 * ModuleDescriptor}. </p> 64 * 65 * <p> The {@link #defineModulesWithOneLoader defineModulesWithOneLoader} and 66 * {@link #defineModulesWithManyLoaders defineModulesWithManyLoaders} methods 67 * provide convenient ways to create a {@code Layer} where all modules are 68 * mapped to a single class loader or where each module is mapped to its own 69 * class loader. The {@link #defineModules defineModules} method is for more 70 * advanced cases where modules are mapped to custom class loaders by means of 71 * a function specified to the method. </p> 72 * 73 * <p> A Java virtual machine has at least one non-empty layer, the {@link 74 * #boot() boot} layer, that is created when the Java virtual machine is 75 * started. The <em>system modules</em>, including {@code java.base}, are in 76 * the boot layer. The modules in the boot layer are mapped to the bootstrap 77 * class loader and other class loaders that are built-in into the ava virtual 78 * machine. The boot layer will often be the {@link #parent() parent} when 79 * creating additional layers. </p> 80 * 81 * <p> As when creating a {@code Configuration}, 82 * {@link ModuleDescriptor#isAutomatic() automatic} modules receive 83 * <a href="../module/Configuration.html#automaticmoduleresolution">special 84 * treatment</a> when creating a layer. An automatic module is created in the 85 * Java virtual machine as a {@code Module} that reads every unnamed {@code 86 * Module} in the Java virtual machine. </p> 87 * 88 * <p> Unless otherwise specified, passing a {@code null} argument to a method 89 * in this class causes a {@link NullPointerException NullPointerException} to 90 * be thrown. </p> 91 * 92 * <h3> Example usage: </h3> 93 * 94 * <p> This example creates a configuration by resolving a module named 95 * "{@code myapp}" with the configuration for the boot layer as the parent. It 96 * then creates a new layer with the modules in this configuration. All modules 97 * are defined to the same class loader. </p> 98 * 99 * <pre>{@code 100 * ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3); 101 * 102 * Layer parent = Layer.boot(); 103 * 104 * Configuration cf = parent.configuration() 105 * .resolveRequires(finder, ModuleFinder.empty(), Set.of("myapp")); 106 * 107 * ClassLoader scl = ClassLoader.getSystemClassLoader(); 108 * 109 * Layer layer = parent.defineModulesWithOneLoader(cf, scl); 110 * 111 * Class<?> c = layer.findLoader("myapp").loadClass("app.Main"); 112 * }</pre> 113 * 114 * @since 9 115 * @see Module#getLayer() 116 */ 117 118 public final class Layer { 119 120 // the empty Layer 121 private static final Layer EMPTY_LAYER 122 = new Layer(Configuration.empty(), null, null); 123 124 // the configuration from which this Layer was created 125 private final Configuration cf; 126 127 // parent layer, null in the case of the empty layer 128 private final Layer parent; 129 130 // maps module name to jlr.Module 131 private final Map<String, Module> nameToModule; 132 133 134 /** 135 * Creates a new Layer from the modules in the given configuration. 136 */ 137 private Layer(Configuration cf, 138 Layer parent, 139 Function<String, ClassLoader> clf) 140 { 141 this.cf = cf; 142 this.parent = parent; 143 144 Map<String, Module> map; 145 if (parent == null) { 146 map = Collections.emptyMap(); 147 } else { 148 map = Module.defineModules(cf, clf, this); 149 } 150 this.nameToModule = map; // no need to do defensive copy 151 } 152 153 154 /** 155 * Creates a new layer, with this layer as its parent, by defining the 156 * modules in the given {@code Configuration} to the Java virtual machine. 157 * This method creates one class loader and defines all modules to that 158 * class loader. 159 * 160 * <p> The class loader created by this method implements <em>direct 161 * delegation</em> when loading types from modules. When its {@link 162 * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to 163 * load a class then it uses the package name of the class to map it to a 164 * module. This may be a module in this layer and hence defined to the same 165 * class loader. It may be a package in a module in a parent layer that is 166 * exported to one or more of the modules in this layer. The class 167 * loader delegates to the class loader of the module, throwing {@code 168 * ClassNotFoundException} if not found by that class loader. 169 * 170 * When {@code loadClass} is invoked to load classes that do not map to a 171 * module then it delegates to the parent class loader. </p> 172 * 173 * <p> Attempting to create a layer with all modules defined to the same 174 * class loader can fail for the following reasons: 175 * 176 * <ul> 177 * 178 * <li><p> <em>Overlapping packages</em>: Two or more modules in the 179 * configuration have the same package (exported or concealed). </p></li> 180 * 181 * <li><p> <em>Split delegation</em>: The resulting class loader would 182 * need to delegate to more than one class loader in order to load types 183 * in a specific package. </p></li> 184 * 185 * </ul> 186 * 187 * <p> If there is a security manager then the class loader created by 188 * this method will load classes and resources with privileges that are 189 * restricted by the calling context of this method. </p> 190 * 191 * @param cf 192 * The configuration for the layer 193 * @param parentLoader 194 * The parent class loader for the class loader created by this 195 * method; may be {@code null} for the bootstrap class loader 196 * 197 * @return The newly created layer 198 * 199 * @throws IllegalArgumentException 200 * If the parent of the given configuration is not the configuration 201 * for this layer 202 * @throws LayerInstantiationException 203 * If all modules cannot be defined to the same class loader for any 204 * of the reasons listed above 205 * @throws SecurityException 206 * If {@code RuntimePermission("createClassLoader")} or 207 * {@code RuntimePermission("getClassLoader")} is denied by 208 * the security manager 209 * 210 * @see #findLoader 211 */ 212 public Layer defineModulesWithOneLoader(Configuration cf, 213 ClassLoader parentLoader) 214 { 215 checkConfiguration(cf); 216 checkCreateClassLoaderPermission(); 217 checkGetClassLoaderPermission(); 218 219 Loader loader; 220 try { 221 loader = new Loader(cf.modules(), parentLoader); 222 loader.initRemotePackageMap(cf, this); 223 } catch (IllegalArgumentException e) { 224 throw new LayerInstantiationException(e.getMessage()); 225 } 226 return new Layer(cf, this, mn -> loader); 227 } 228 229 230 /** 231 * Creates a new layer, with this layer as its parent, by defining the 232 * modules in the given {@code Configuration} to the Java virtual machine. 233 * Each module is defined to its own {@link ClassLoader} created by this 234 * method. The {@link ClassLoader#getParent() parent} of each class loader 235 * is the given parent class loader. 236 * 237 * <p> The class loaders created by this method implement <em>direct 238 * delegation</em> when loading types from modules. When {@link 239 * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to 240 * load a class then it uses the package name of the class to map it to a 241 * module. The package may be in the module defined to the class loader. 242 * The package may be exported by another module in this layer to the 243 * module defined to the class loader. It may be in a package exported by a 244 * module in a parent layer. The class loader delegates to the class loader 245 * of the module, throwing {@code ClassNotFoundException} if not found by 246 * that class loader. 247 * 248 * When {@code loadClass} is invoked to load classes that do not map to a 249 * module then it delegates to the parent class loader. </p> 250 * 251 * <p> If there is a security manager then the class loaders created by 252 * this method will load classes and resources with privileges that are 253 * restricted by the calling context of this method. </p> 254 * 255 * @param cf 256 * The configuration for the layer 257 * @param parentLoader 258 * The parent class loader for each of the class loaders created by 259 * this method; may be {@code null} for the bootstrap class loader 260 * 261 * @return The newly created layer 262 * 263 * @throws IllegalArgumentException 264 * If the parent of the given configuration is not the configuration 265 * for this layer 266 * @throws SecurityException 267 * If {@code RuntimePermission("createClassLoader")} or 268 * {@code RuntimePermission("getClassLoader")} is denied by 269 * the security manager 270 * 271 * @see #findLoader 272 */ 273 public Layer defineModulesWithManyLoaders(Configuration cf, 274 ClassLoader parentLoader) 275 { 276 checkConfiguration(cf); 277 checkCreateClassLoaderPermission(); 278 checkGetClassLoaderPermission(); 279 280 LoaderPool pool = new LoaderPool(cf, this, parentLoader); 281 return new Layer(cf, this, pool::loaderFor); 282 } 283 284 285 /** 286 * Creates a new layer, with this layer as its parent, by defining the 287 * modules in the given {@code Configuration} to the Java virtual machine. 288 * Each module is mapped, by name, to its class loader by means of the 289 * given function. The class loader delegation implemented by these class 290 * loaders must respect module readability. In addition, the caller needs 291 * to arrange that the class loaders are ready to load from these module 292 * before there are any attempts to load classes or resources. 293 * 294 * <p> Creating a {@code Layer} can fail for the following reasons: </p> 295 * 296 * <ul> 297 * 298 * <li><p> Two or more modules with the same package (exported or 299 * concealed) are mapped to the same class loader. </p></li> 300 * 301 * <li><p> A module is mapped to a class loader that already has a 302 * module of the same name defined to it. </p></li> 303 * 304 * <li><p> A module is mapped to a class loader that has already 305 * defined types in any of the packages in the module. </p></li> 306 * 307 * </ul> 308 * 309 * <p> If the function to map a module name to class loader throws an error 310 * or runtime exception then it is propagated to the caller of this method. 311 * </p> 312 * 313 * @apiNote It is implementation specific as to whether creating a Layer 314 * with this method is an atomic operation or not. Consequentially it is 315 * possible for this method to fail with some modules, but not all, defined 316 * to Java virtual machine. 317 * 318 * @param cf 319 * The configuration for the layer 320 * @param clf 321 * The function to map a module name to a class loader 322 * 323 * @return The newly created layer 324 * 325 * @throws IllegalArgumentException 326 * If the parent of the given configuration is not the configuration 327 * for this layer 328 * @throws LayerInstantiationException 329 * If creating the {@code Layer} fails for any of the reasons 330 * listed above 331 * @throws SecurityException 332 * If {@code RuntimePermission("getClassLoader")} is denied by 333 * the security manager 334 */ 335 public Layer defineModules(Configuration cf, 336 Function<String, ClassLoader> clf) 337 { 338 checkConfiguration(cf); 339 Objects.requireNonNull(clf); 340 341 checkGetClassLoaderPermission(); 342 343 // For now, no two modules in the boot Layer may contain the same 344 // package so we use a simple check for the boot Layer to keep 345 // the overhead at startup to a minimum 346 if (boot() == null) { 347 checkBootModulesForDuplicatePkgs(cf); 348 } else { 349 checkForDuplicatePkgs(cf, clf); 350 } 351 352 try { 353 return new Layer(cf, this, clf); 354 } catch (IllegalArgumentException iae) { 355 // IAE is thrown by VM when defining the module fails 356 throw new LayerInstantiationException(iae.getMessage()); 357 } 358 } 359 360 361 private void checkConfiguration(Configuration cf) { 362 Objects.requireNonNull(cf); 363 364 Optional<Configuration> oparent = cf.parent(); 365 if (!oparent.isPresent() || oparent.getWhenPresent() != this.configuration()) { 366 throw new IllegalArgumentException( 367 "Parent of configuration != configuration of this Layer"); 368 } 369 } 370 371 private static void checkCreateClassLoaderPermission() { 372 SecurityManager sm = System.getSecurityManager(); 373 if (sm != null) 374 sm.checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION); 375 } 376 377 private static void checkGetClassLoaderPermission() { 378 SecurityManager sm = System.getSecurityManager(); 379 if (sm != null) 380 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); 381 } 382 383 /** 384 * Checks a configuration for the boot Layer to ensure that no two modules 385 * have the same package. 386 * 387 * @throws LayerInstantiationException 388 */ 389 private static void checkBootModulesForDuplicatePkgs(Configuration cf) { 390 Map<String, String> packageToModule = new HashMap<>(); 391 for (ResolvedModule resolvedModule : cf.modules()) { 392 ModuleDescriptor descriptor = resolvedModule.reference().descriptor(); 393 String name = descriptor.name(); 394 for (String p : descriptor.packages()) { 395 String other = packageToModule.putIfAbsent(p, name); 396 if (other != null) { 397 throw fail("Package " + p + " in both module " 398 + name + " and module " + other); 399 } 400 } 401 } 402 } 403 404 /** 405 * Checks a configuration and the module-to-loader mapping to ensure that 406 * no two modules mapped to the same class loader have the same package. 407 * It also checks that no two automatic modules have the same package. 408 * 409 * @throws LayerInstantiationException 410 */ 411 private static void checkForDuplicatePkgs(Configuration cf, 412 Function<String, ClassLoader> clf) 413 { 414 // HashMap allows null keys 415 Map<ClassLoader, Set<String>> loaderToPackages = new HashMap<>(); 416 for (ResolvedModule resolvedModule : cf.modules()) { 417 ModuleDescriptor descriptor = resolvedModule.reference().descriptor(); 418 ClassLoader loader = clf.apply(descriptor.name()); 419 420 Set<String> loaderPackages 421 = loaderToPackages.computeIfAbsent(loader, k -> new HashSet<>()); 422 423 for (String pkg : descriptor.packages()) { 424 boolean added = loaderPackages.add(pkg); 425 if (!added) { 426 throw fail("More than one module with package %s mapped" + 427 " to the same class loader", pkg); 428 } 429 } 430 } 431 } 432 433 /** 434 * Creates a LayerInstantiationException with the a message formatted from 435 * the given format string and arguments. 436 */ 437 private static LayerInstantiationException fail(String fmt, Object ... args) { 438 String msg = String.format(fmt, args); 439 return new LayerInstantiationException(msg); 440 } 441 442 443 /** 444 * Returns the configuration for this layer. 445 * 446 * @return The configuration for this layer 447 */ 448 public Configuration configuration() { 449 return cf; 450 } 451 452 453 /** 454 * Returns this layer's parent unless this is the {@linkplain #empty empty 455 * layer}, which has no parent. 456 * 457 * @return This layer's parent 458 */ 459 public Optional<Layer> parent() { 460 return Optional.ofNullable(parent); 461 } 462 463 464 /** 465 * Returns a set of the modules in this layer. 466 * 467 * @return A possibly-empty unmodifiable set of the modules in this layer 468 */ 469 public Set<Module> modules() { 470 return Collections.unmodifiableSet( 471 nameToModule.values().stream().collect(Collectors.toSet())); 472 } 473 474 475 /** 476 * Returns the module with the given name in this layer, or if not in this 477 * layer, the {@linkplain #parent parent} layer. 478 * 479 * @param name 480 * The name of the module to find 481 * 482 * @return The module with the given name or an empty {@code Optional} 483 * if there isn't a module with this name in this layer or any 484 * parent layer 485 */ 486 public Optional<Module> findModule(String name) { 487 Module m = nameToModule.get(Objects.requireNonNull(name)); 488 if (m != null) 489 return Optional.of(m); 490 return parent().flatMap(l -> l.findModule(name)); 491 } 492 493 494 /** 495 * Returns the {@code ClassLoader} for the module with the given name. If 496 * a module of the given name is not in this layer then the {@link #parent} 497 * layer is checked. 498 * 499 * <p> If there is a security manager then its {@code checkPermission} 500 * method is called with a {@code RuntimePermission("getClassLoader")} 501 * permission to check that the caller is allowed to get access to the 502 * class loader. </p> 503 * 504 * @apiNote This method does not return an {@code Optional<ClassLoader>} 505 * because `null` must be used to represent the bootstrap class loader. 506 * 507 * @param name 508 * The name of the module to find 509 * 510 * @return The ClassLoader that the module is defined to 511 * 512 * @throws IllegalArgumentException if a module of the given name is not 513 * defined in this layer or any parent of this layer 514 * 515 * @throws SecurityException if denied by the security manager 516 */ 517 public ClassLoader findLoader(String name) { 518 Module m = nameToModule.get(Objects.requireNonNull(name)); 519 if (m != null) 520 return m.getClassLoader(); 521 Optional<Layer> ol = parent(); 522 if (ol.isPresent()) 523 return ol.getWhenPresent().findLoader(name); 524 throw new IllegalArgumentException("Module " + name 525 + " not known to this layer"); 526 } 527 528 529 /** 530 * Returns the <em>empty</em> layer. There are no modules in the empty 531 * layer. It has no parent. 532 * 533 * @return The empty layer 534 */ 535 public static Layer empty() { 536 return EMPTY_LAYER; 537 } 538 539 540 /** 541 * Returns the boot layer. The boot layer contains at least one module, 542 * {@code java.base}. Its parent is the {@link #empty() empty} layer. 543 * 544 * @apiNote This method returns {@code null} during startup and before 545 * the boot layer is fully initialized. 546 * 547 * @return The boot layer 548 */ 549 public static Layer boot() { 550 return SharedSecrets.getJavaLangAccess().getBootLayer(); 551 } 552 }