1 /* 2 * Copyright (c) 2014, 2022, 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; 27 28 import java.lang.module.Configuration; 29 import java.lang.module.ModuleDescriptor; 30 import java.lang.module.ResolvedModule; 31 import java.util.ArrayDeque; 32 import java.util.ArrayList; 33 import java.util.Collections; 34 import java.util.Deque; 35 import java.util.HashMap; 36 import java.util.HashSet; 37 import java.util.List; 38 import java.util.Map; 39 import java.util.Objects; 40 import java.util.Optional; 41 import java.util.Set; 42 import java.util.concurrent.CopyOnWriteArrayList; 43 import java.util.function.Function; 44 import java.util.stream.Collectors; 45 import java.util.stream.Stream; 46 47 import jdk.internal.javac.PreviewFeature; 48 import jdk.internal.javac.Restricted; 49 import jdk.internal.loader.ClassLoaderValue; 50 import jdk.internal.loader.Loader; 51 import jdk.internal.loader.LoaderPool; 52 import jdk.internal.module.ServicesCatalog; 53 import jdk.internal.misc.CDS; 54 import jdk.internal.reflect.CallerSensitive; 55 import jdk.internal.reflect.Reflection; 56 import jdk.internal.vm.annotation.Stable; 57 import sun.security.util.SecurityConstants; 58 59 /** 60 * A layer of modules in the Java virtual machine. 61 * 62 * <p> A layer is created from a graph of modules in a {@link Configuration} 63 * and a function that maps each module to a {@link ClassLoader}. 64 * Creating a layer informs the Java virtual machine about the classes that 65 * may be loaded from the modules so that the Java virtual machine knows which 66 * module that each class is a member of. </p> 67 * 68 * <p> Creating a layer creates a {@link Module} object for each {@link 69 * ResolvedModule} in the configuration. For each resolved module that is 70 * {@link ResolvedModule#reads() read}, the {@code Module} {@link 71 * Module#canRead reads} the corresponding run-time {@code Module}, which may 72 * be in the same layer or a {@link #parents() parent} layer. </p> 73 * 74 * <p> The {@link #defineModulesWithOneLoader defineModulesWithOneLoader} and 75 * {@link #defineModulesWithManyLoaders defineModulesWithManyLoaders} methods 76 * provide convenient ways to create a module layer where all modules are 77 * mapped to a single class loader or where each module is mapped to its own 78 * class loader. The {@link #defineModules defineModules} method is for more 79 * advanced cases where modules are mapped to custom class loaders by means of 80 * a function specified to the method. Each of these methods has an instance 81 * and static variant. The instance methods create a layer with the receiver 82 * as the parent layer. The static methods are for more advanced cases where 83 * there can be more than one parent layer or where a {@link 84 * ModuleLayer.Controller Controller} is needed to control modules in the layer 85 * </p> 86 * 87 * <p> A Java virtual machine has at least one non-empty layer, the {@link 88 * #boot() boot} layer, that is created when the Java virtual machine is 89 * started. The boot layer contains module {@code java.base} and is the only 90 * layer in the Java virtual machine with a module named "{@code java.base}". 91 * The modules in the boot layer are mapped to the bootstrap class loader and 92 * other class loaders that are <a href="ClassLoader.html#builtinLoaders"> 93 * built-in</a> into the Java virtual machine. The boot layer will often be 94 * the {@link #parents() parent} when creating additional layers. </p> 95 * 96 * <p> Each {@code Module} in a layer is created so that it {@link 97 * Module#isExported(String) exports} and {@link Module#isOpen(String) opens} 98 * the packages described by its {@link ModuleDescriptor}. Qualified exports 99 * (where a package is exported to a set of target modules rather than all 100 * modules) are reified when creating the layer as follows: </p> 101 * <ul> 102 * <li> If module {@code X} exports a package to {@code Y}, and if the 103 * runtime {@code Module} {@code X} reads {@code Module} {@code Y}, then 104 * the package is exported to {@code Module} {@code Y} (which may be in 105 * the same layer as {@code X} or a parent layer). </li> 106 * 107 * <li> If module {@code X} exports a package to {@code Y}, and if the 108 * runtime {@code Module} {@code X} does not read {@code Y} then target 109 * {@code Y} is located as if by invoking {@link #findModule(String) 110 * findModule} to find the module in the layer or its parent layers. If 111 * {@code Y} is found then the package is exported to the instance of 112 * {@code Y} that was found. If {@code Y} is not found then the qualified 113 * export is ignored. </li> 114 * </ul> 115 * 116 * <p> Qualified opens are handled in same way as qualified exports. </p> 117 * 118 * <p> As when creating a {@code Configuration}, 119 * {@link ModuleDescriptor#isAutomatic() automatic} modules receive special 120 * treatment when creating a layer. An automatic module is created in the 121 * Java virtual machine as a {@code Module} that reads every unnamed {@code 122 * Module} in the Java virtual machine. </p> 123 * 124 * <p> Unless otherwise specified, passing a {@code null} argument to a method 125 * in this class causes a {@link NullPointerException NullPointerException} to 126 * be thrown. </p> 127 * 128 * <h2> Example </h2> 129 * 130 * <p> This example creates a configuration by resolving a module named 131 * "{@code myapp}" with the configuration for the boot layer as the parent. It 132 * then creates a new layer with the modules in this configuration. All modules 133 * are defined to the same class loader. </p> 134 * 135 * {@snippet : 136 * ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3); 137 * ModuleLayer parent = ModuleLayer.boot(); 138 * Configuration cf = parent.configuration() 139 * .resolve(finder, ModuleFinder.of(), Set.of("myapp")); 140 * ClassLoader scl = ClassLoader.getSystemClassLoader(); 141 * ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl); 142 * Class<?> c = layer.findLoader("myapp").loadClass("app.Main"); 143 * } 144 * 145 * @since 9 146 * @see Module#getLayer() 147 */ 148 149 public final class ModuleLayer { 150 151 // the empty layer (may be initialized from the CDS archive) 152 private static @Stable ModuleLayer EMPTY_LAYER; 153 static { 154 CDS.initializeFromArchive(ModuleLayer.class); 155 if (EMPTY_LAYER == null) { 156 // create a new empty layer if there is no archived version. 157 EMPTY_LAYER = new ModuleLayer(Configuration.empty(), List.of(), null); 158 } 159 } 160 161 // the configuration from which this layer was created 162 private final Configuration cf; 163 164 // parent layers, empty in the case of the empty layer 165 private final List<ModuleLayer> parents; 166 167 // maps module name to jlr.Module 168 private final Map<String, Module> nameToModule; 169 170 /** 171 * Creates a new module layer from the modules in the given configuration. 172 */ 173 private ModuleLayer(Configuration cf, 174 List<ModuleLayer> parents, 175 Function<String, ClassLoader> clf) 176 { 177 this.cf = cf; 178 this.parents = parents; // no need to do defensive copy 179 180 Map<String, Module> map; 181 if (parents.isEmpty()) { 182 map = Map.of(); 183 } else { 184 map = Module.defineModules(cf, clf, this); 185 } 186 this.nameToModule = map; // no need to do defensive copy 187 } 188 189 /** 190 * Controls a module layer. The static methods defined by {@link ModuleLayer} 191 * to create module layers return a {@code Controller} that can be used to 192 * control modules in the layer. 193 * 194 * <p> Unless otherwise specified, passing a {@code null} argument to a 195 * method in this class causes a {@link NullPointerException 196 * NullPointerException} to be thrown. </p> 197 * 198 * @apiNote Care should be taken with {@code Controller} objects, they 199 * should never be shared with untrusted code. 200 * 201 * @since 9 202 */ 203 public static final class Controller { 204 private final ModuleLayer layer; 205 206 Controller(ModuleLayer layer) { 207 this.layer = layer; 208 } 209 210 /** 211 * Returns the layer that this object controls. 212 * 213 * @return the module layer 214 */ 215 public ModuleLayer layer() { 216 return layer; 217 } 218 219 private void ensureInLayer(Module source) { 220 if (source.getLayer() != layer) 221 throw new IllegalArgumentException(source + " not in layer"); 222 } 223 224 225 /** 226 * Updates module {@code source} in the layer to read module 227 * {@code target}. This method is a no-op if {@code source} already 228 * reads {@code target}. 229 * 230 * @implNote <em>Read edges</em> added by this method are <em>weak</em> 231 * and do not prevent {@code target} from being GC'ed when {@code source} 232 * is strongly reachable. 233 * 234 * @param source 235 * The source module 236 * @param target 237 * The target module to read 238 * 239 * @return This controller 240 * 241 * @throws IllegalArgumentException 242 * If {@code source} is not in the module layer 243 * 244 * @see Module#addReads 245 */ 246 public Controller addReads(Module source, Module target) { 247 ensureInLayer(source); 248 source.implAddReads(target); 249 return this; 250 } 251 252 /** 253 * Updates module {@code source} in the layer to export a package to 254 * module {@code target}. This method is a no-op if {@code source} 255 * already exports the package to at least {@code target}. 256 * 257 * @param source 258 * The source module 259 * @param pn 260 * The package name 261 * @param target 262 * The target module 263 * 264 * @return This controller 265 * 266 * @throws IllegalArgumentException 267 * If {@code source} is not in the module layer or the package 268 * is not in the source module 269 * 270 * @see Module#addExports 271 */ 272 public Controller addExports(Module source, String pn, Module target) { 273 ensureInLayer(source); 274 source.implAddExports(pn, target); 275 return this; 276 } 277 278 /** 279 * Updates module {@code source} in the layer to open a package to 280 * module {@code target}. This method is a no-op if {@code source} 281 * already opens the package to at least {@code target}. 282 * 283 * @param source 284 * The source module 285 * @param pn 286 * The package name 287 * @param target 288 * The target module 289 * 290 * @return This controller 291 * 292 * @throws IllegalArgumentException 293 * If {@code source} is not in the module layer or the package 294 * is not in the source module 295 * 296 * @see Module#addOpens 297 */ 298 public Controller addOpens(Module source, String pn, Module target) { 299 ensureInLayer(source); 300 source.implAddOpens(pn, target); 301 return this; 302 } 303 304 /** 305 * Enables native access for a module in the layer if the caller's module 306 * has native access. 307 * 308 * <p> This method is <a href="foreign/package-summary.html#restricted"><em>restricted</em></a>. 309 * Restricted methods are unsafe, and, if used incorrectly, their use might crash 310 * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain 311 * from depending on restricted methods, and use safe and supported functionalities, 312 * where possible. 313 * 314 * @param target 315 * The module to update 316 * 317 * @return This controller 318 * 319 * @throws IllegalArgumentException 320 * If {@code target} is not in the module layer 321 * 322 * @throws IllegalCallerException 323 * If the caller is in a module that does not have native access enabled 324 * 325 * @since 20 326 */ 327 @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) 328 @CallerSensitive 329 @Restricted 330 public Controller enableNativeAccess(Module target) { 331 ensureInLayer(target); 332 Reflection.ensureNativeAccess(Reflection.getCallerClass(), Module.class, 333 "enableNativeAccess"); 334 target.implAddEnableNativeAccess(); 335 return this; 336 } 337 } 338 339 340 /** 341 * Creates a new module layer, with this layer as its parent, by defining the 342 * modules in the given {@code Configuration} to the Java virtual machine. 343 * This method creates one class loader and defines all modules to that 344 * class loader. The {@link ClassLoader#getParent() parent} of each class 345 * loader is the given parent class loader. This method works exactly as 346 * specified by the static {@link 347 * #defineModulesWithOneLoader(Configuration,List,ClassLoader) 348 * defineModulesWithOneLoader} method when invoked with this layer as the 349 * parent. In other words, if this layer is {@code thisLayer} then this 350 * method is equivalent to invoking: 351 * <pre> {@code 352 * ModuleLayer.defineModulesWithOneLoader(cf, List.of(thisLayer), parentLoader).layer(); 353 * }</pre> 354 * 355 * @param cf 356 * The configuration for the layer 357 * @param parentLoader 358 * The parent class loader for the class loader created by this 359 * method; may be {@code null} for the bootstrap class loader 360 * 361 * @return The newly created layer 362 * 363 * @throws IllegalArgumentException 364 * If the given configuration has more than one parent or the parent 365 * of the configuration is not the configuration for this layer 366 * @throws LayerInstantiationException 367 * If the layer cannot be created for any of the reasons specified 368 * by the static {@code defineModulesWithOneLoader} method 369 * @throws SecurityException 370 * If {@code RuntimePermission("createClassLoader")} or 371 * {@code RuntimePermission("getClassLoader")} is denied by 372 * the security manager 373 * 374 * @see #findLoader 375 */ 376 public ModuleLayer defineModulesWithOneLoader(Configuration cf, 377 ClassLoader parentLoader) { 378 return defineModulesWithOneLoader(cf, List.of(this), parentLoader).layer(); 379 } 380 381 382 /** 383 * Creates a new module layer, with this layer as its parent, by defining the 384 * modules in the given {@code Configuration} to the Java virtual machine. 385 * Each module is defined to its own {@link ClassLoader} created by this 386 * method. The {@link ClassLoader#getParent() parent} of each class loader 387 * is the given parent class loader. This method works exactly as specified 388 * by the static {@link 389 * #defineModulesWithManyLoaders(Configuration,List,ClassLoader) 390 * defineModulesWithManyLoaders} method when invoked with this layer as the 391 * parent. In other words, if this layer is {@code thisLayer} then this 392 * method is equivalent to invoking: 393 * <pre> {@code 394 * ModuleLayer.defineModulesWithManyLoaders(cf, List.of(thisLayer), parentLoader).layer(); 395 * }</pre> 396 * 397 * @param cf 398 * The configuration for the layer 399 * @param parentLoader 400 * The parent class loader for each of the class loaders created by 401 * this method; may be {@code null} for the bootstrap class loader 402 * 403 * @return The newly created layer 404 * 405 * @throws IllegalArgumentException 406 * If the given configuration has more than one parent or the parent 407 * of the configuration is not the configuration for this layer 408 * @throws LayerInstantiationException 409 * If the layer cannot be created for any of the reasons specified 410 * by the static {@code defineModulesWithManyLoaders} method 411 * @throws SecurityException 412 * If {@code RuntimePermission("createClassLoader")} or 413 * {@code RuntimePermission("getClassLoader")} is denied by 414 * the security manager 415 * 416 * @see #findLoader 417 */ 418 public ModuleLayer defineModulesWithManyLoaders(Configuration cf, 419 ClassLoader parentLoader) { 420 return defineModulesWithManyLoaders(cf, List.of(this), parentLoader).layer(); 421 } 422 423 424 /** 425 * Creates a new module layer, with this layer as its parent, by defining the 426 * modules in the given {@code Configuration} to the Java virtual machine. 427 * Each module is mapped, by name, to its class loader by means of the 428 * given function. This method works exactly as specified by the static 429 * {@link #defineModules(Configuration,List,Function) defineModules} 430 * method when invoked with this layer as the parent. In other words, if 431 * this layer is {@code thisLayer} then this method is equivalent to 432 * invoking: 433 * <pre> {@code 434 * ModuleLayer.defineModules(cf, List.of(thisLayer), clf).layer(); 435 * }</pre> 436 * 437 * @param cf 438 * The configuration for the layer 439 * @param clf 440 * The function to map a module name to a class loader 441 * 442 * @return The newly created layer 443 * 444 * @throws IllegalArgumentException 445 * If the given configuration has more than one parent or the parent 446 * of the configuration is not the configuration for this layer 447 * @throws LayerInstantiationException 448 * If the layer cannot be created for any of the reasons specified 449 * by the static {@code defineModules} method 450 * @throws SecurityException 451 * If {@code RuntimePermission("getClassLoader")} is denied by 452 * the security manager 453 */ 454 public ModuleLayer defineModules(Configuration cf, 455 Function<String, ClassLoader> clf) { 456 return defineModules(cf, List.of(this), clf).layer(); 457 } 458 459 /** 460 * Creates a new module layer by defining the modules in the given {@code 461 * Configuration} to the Java virtual machine. This method creates one 462 * class loader and defines all modules to that class loader. 463 * 464 * <p> The class loader created by this method implements <em>direct 465 * delegation</em> when loading classes from modules. If the {@link 466 * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to 467 * load a class then it uses the package name of the class to map it to a 468 * module. This may be a module in this layer and hence defined to the same 469 * class loader. It may be a package in a module in a parent layer that is 470 * exported to one or more of the modules in this layer. The class 471 * loader delegates to the class loader of the module, throwing {@code 472 * ClassNotFoundException} if not found by that class loader. 473 * When {@code loadClass} is invoked to load classes that do not map to a 474 * module then it delegates to the parent class loader. </p> 475 * 476 * <p> The class loader created by this method locates resources 477 * ({@link ClassLoader#getResource(String) getResource}, {@link 478 * ClassLoader#getResources(String) getResources}, and other resource 479 * methods) in all modules in the layer before searching the parent class 480 * loader. </p> 481 * 482 * <p> Attempting to create a layer with all modules defined to the same 483 * class loader can fail for the following reasons: 484 * 485 * <ul> 486 * 487 * <li><p> <em>Overlapping packages</em>: Two or more modules in the 488 * configuration have the same package. </p></li> 489 * 490 * <li><p> <em>Split delegation</em>: The resulting class loader would 491 * need to delegate to more than one class loader in order to load 492 * classes in a specific package. </p></li> 493 * 494 * </ul> 495 * 496 * <p> In addition, a layer cannot be created if the configuration contains 497 * a module named "{@code java.base}", or a module contains a package named 498 * "{@code java}" or a package with a name starting with "{@code java.}". </p> 499 * 500 * <p> If there is a security manager then the class loader created by 501 * this method will load classes and resources with privileges that are 502 * restricted by the calling context of this method. </p> 503 * 504 * @param cf 505 * The configuration for the layer 506 * @param parentLayers 507 * The list of parent layers in search order 508 * @param parentLoader 509 * The parent class loader for the class loader created by this 510 * method; may be {@code null} for the bootstrap class loader 511 * 512 * @return A controller that controls the newly created layer 513 * 514 * @throws IllegalArgumentException 515 * If the parent(s) of the given configuration do not match the 516 * configuration of the parent layers, including order 517 * @throws LayerInstantiationException 518 * If all modules cannot be defined to the same class loader for any 519 * of the reasons listed above 520 * @throws SecurityException 521 * If {@code RuntimePermission("createClassLoader")} or 522 * {@code RuntimePermission("getClassLoader")} is denied by 523 * the security manager 524 * 525 * @see #findLoader 526 */ 527 public static Controller defineModulesWithOneLoader(Configuration cf, 528 List<ModuleLayer> parentLayers, 529 ClassLoader parentLoader) 530 { 531 List<ModuleLayer> parents = List.copyOf(parentLayers); 532 checkConfiguration(cf, parents); 533 534 checkCreateClassLoaderPermission(); 535 checkGetClassLoaderPermission(); 536 537 try { 538 Loader loader = new Loader(cf.modules(), parentLoader); 539 loader.initRemotePackageMap(cf, parents); 540 ModuleLayer layer = new ModuleLayer(cf, parents, mn -> loader); 541 return new Controller(layer); 542 } catch (IllegalArgumentException | IllegalStateException e) { 543 throw new LayerInstantiationException(e.getMessage()); 544 } 545 } 546 547 /** 548 * Creates a new module layer by defining the modules in the given {@code 549 * Configuration} to the Java virtual machine. Each module is defined to 550 * its own {@link ClassLoader} created by this method. The {@link 551 * ClassLoader#getParent() parent} of each class loader is the given parent 552 * class loader. 553 * 554 * <p> The class loaders created by this method implement <em>direct 555 * delegation</em> when loading classes from modules. If the {@link 556 * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to 557 * load a class then it uses the package name of the class to map it to a 558 * module. The package may be in the module defined to the class loader. 559 * The package may be exported by another module in this layer to the 560 * module defined to the class loader. It may be in a package exported by a 561 * module in a parent layer. The class loader delegates to the class loader 562 * of the module, throwing {@code ClassNotFoundException} if not found by 563 * that class loader. When {@code loadClass} is invoked to load a class 564 * that does not map to a module then it delegates to the parent class 565 * loader. </p> 566 * 567 * <p> The class loaders created by this method locate resources 568 * ({@link ClassLoader#getResource(String) getResource}, {@link 569 * ClassLoader#getResources(String) getResources}, and other resource 570 * methods) in the module defined to the class loader before searching 571 * the parent class loader. </p> 572 * 573 * <p> If there is a security manager then the class loaders created by 574 * this method will load classes and resources with privileges that are 575 * restricted by the calling context of this method. </p> 576 * 577 * @param cf 578 * The configuration for the layer 579 * @param parentLayers 580 * The list of parent layers in search order 581 * @param parentLoader 582 * The parent class loader for each of the class loaders created by 583 * this method; may be {@code null} for the bootstrap class loader 584 * 585 * @return A controller that controls the newly created layer 586 * 587 * @throws IllegalArgumentException 588 * If the parent(s) of the given configuration do not match the 589 * configuration of the parent layers, including order 590 * @throws LayerInstantiationException 591 * If the layer cannot be created because the configuration contains 592 * a module named "{@code java.base}" or a module contains a package 593 * named "{@code java}" or a package with a name starting with 594 * "{@code java.}" 595 * 596 * @throws SecurityException 597 * If {@code RuntimePermission("createClassLoader")} or 598 * {@code RuntimePermission("getClassLoader")} is denied by 599 * the security manager 600 * 601 * @see #findLoader 602 */ 603 public static Controller defineModulesWithManyLoaders(Configuration cf, 604 List<ModuleLayer> parentLayers, 605 ClassLoader parentLoader) 606 { 607 List<ModuleLayer> parents = List.copyOf(parentLayers); 608 checkConfiguration(cf, parents); 609 610 checkCreateClassLoaderPermission(); 611 checkGetClassLoaderPermission(); 612 613 LoaderPool pool = new LoaderPool(cf, parents, parentLoader); 614 try { 615 ModuleLayer layer = new ModuleLayer(cf, parents, pool::loaderFor); 616 return new Controller(layer); 617 } catch (IllegalArgumentException | IllegalStateException e) { 618 throw new LayerInstantiationException(e.getMessage()); 619 } 620 } 621 622 /** 623 * Creates a new module layer by defining the modules in the given {@code 624 * Configuration} to the Java virtual machine. The given function maps each 625 * module in the configuration, by name, to a class loader. Creating the 626 * layer informs the Java virtual machine about the classes that may be 627 * loaded so that the Java virtual machine knows which module that each 628 * class is a member of. 629 * 630 * <p> The class loader delegation implemented by the class loaders must 631 * respect module readability. The class loaders should be 632 * {@link ClassLoader#registerAsParallelCapable parallel-capable} so as to 633 * avoid deadlocks during class loading. In addition, the entity creating 634 * a new layer with this method should arrange that the class loaders be 635 * ready to load from these modules before there are any attempts to load 636 * classes or resources. </p> 637 * 638 * <p> Creating a layer can fail for the following reasons: </p> 639 * 640 * <ul> 641 * 642 * <li><p> Two or more modules with the same package are mapped to the 643 * same class loader. </p></li> 644 * 645 * <li><p> A module is mapped to a class loader that already has a 646 * module of the same name defined to it. </p></li> 647 * 648 * <li><p> A module is mapped to a class loader that has already 649 * defined types in any of the packages in the module. </p></li> 650 * 651 * </ul> 652 * 653 * <p> In addition, a layer cannot be created if the configuration contains 654 * a module named "{@code java.base}", a configuration contains a module 655 * with a package named "{@code java}" or a package name starting with 656 * "{@code java.}", or the function to map a module name to a class loader 657 * returns {@code null} or the {@linkplain ClassLoader#getPlatformClassLoader() 658 * platform class loader}. </p> 659 * 660 * <p> If the function to map a module name to class loader throws an error 661 * or runtime exception then it is propagated to the caller of this method. 662 * </p> 663 * 664 * @apiNote It is implementation specific as to whether creating a layer 665 * with this method is an atomic operation or not. Consequently it is 666 * possible for this method to fail with some modules, but not all, defined 667 * to the Java virtual machine. 668 * 669 * @param cf 670 * The configuration for the layer 671 * @param parentLayers 672 * The list of parent layers in search order 673 * @param clf 674 * The function to map a module name to a class loader 675 * 676 * @return A controller that controls the newly created layer 677 * 678 * @throws IllegalArgumentException 679 * If the parent(s) of the given configuration do not match the 680 * configuration of the parent layers, including order 681 * @throws LayerInstantiationException 682 * If creating the layer fails for any of the reasons listed above 683 * @throws SecurityException 684 * If {@code RuntimePermission("getClassLoader")} is denied by 685 * the security manager 686 */ 687 public static Controller defineModules(Configuration cf, 688 List<ModuleLayer> parentLayers, 689 Function<String, ClassLoader> clf) 690 { 691 List<ModuleLayer> parents = List.copyOf(parentLayers); 692 checkConfiguration(cf, parents); 693 Objects.requireNonNull(clf); 694 695 checkGetClassLoaderPermission(); 696 697 // The boot layer is checked during module system initialization 698 if (boot() != null) { 699 checkForDuplicatePkgs(cf, clf); 700 } 701 702 try { 703 ModuleLayer layer = new ModuleLayer(cf, parents, clf); 704 return new Controller(layer); 705 } catch (IllegalArgumentException | IllegalStateException e) { 706 throw new LayerInstantiationException(e.getMessage()); 707 } 708 } 709 710 711 /** 712 * Checks that the parent configurations match the configuration of 713 * the parent layers. 714 */ 715 private static void checkConfiguration(Configuration cf, 716 List<ModuleLayer> parentLayers) 717 { 718 Objects.requireNonNull(cf); 719 720 List<Configuration> parentConfigurations = cf.parents(); 721 if (parentLayers.size() != parentConfigurations.size()) 722 throw new IllegalArgumentException("wrong number of parents"); 723 724 int index = 0; 725 for (ModuleLayer parent : parentLayers) { 726 if (parent.configuration() != parentConfigurations.get(index)) { 727 throw new IllegalArgumentException( 728 "Parent of configuration != configuration of this Layer"); 729 } 730 index++; 731 } 732 } 733 734 private static void checkCreateClassLoaderPermission() { 735 @SuppressWarnings("removal") 736 SecurityManager sm = System.getSecurityManager(); 737 if (sm != null) 738 sm.checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION); 739 } 740 741 private static void checkGetClassLoaderPermission() { 742 @SuppressWarnings("removal") 743 SecurityManager sm = System.getSecurityManager(); 744 if (sm != null) 745 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); 746 } 747 748 /** 749 * Checks a configuration and the module-to-loader mapping to ensure that 750 * no two modules mapped to the same class loader have the same package. 751 * It also checks that no two automatic modules have the same package. 752 * 753 * @throws LayerInstantiationException 754 */ 755 private static void checkForDuplicatePkgs(Configuration cf, 756 Function<String, ClassLoader> clf) 757 { 758 // HashMap allows null keys 759 Map<ClassLoader, Set<String>> loaderToPackages = new HashMap<>(); 760 for (ResolvedModule resolvedModule : cf.modules()) { 761 ModuleDescriptor descriptor = resolvedModule.reference().descriptor(); 762 ClassLoader loader = clf.apply(descriptor.name()); 763 764 Set<String> loaderPackages 765 = loaderToPackages.computeIfAbsent(loader, k -> new HashSet<>()); 766 767 for (String pkg : descriptor.packages()) { 768 boolean added = loaderPackages.add(pkg); 769 if (!added) { 770 throw fail("More than one module with package %s mapped" + 771 " to the same class loader", pkg); 772 } 773 } 774 } 775 } 776 777 /** 778 * Creates a LayerInstantiationException with the message formatted from 779 * the given format string and arguments. 780 */ 781 private static LayerInstantiationException fail(String fmt, Object ... args) { 782 String msg = String.format(fmt, args); 783 return new LayerInstantiationException(msg); 784 } 785 786 787 /** 788 * Returns the configuration for this layer. 789 * 790 * @return The configuration for this layer 791 */ 792 public Configuration configuration() { 793 return cf; 794 } 795 796 /** 797 * Returns an unmodifiable list of this layer's parents, in search 798 * order. If this is the {@linkplain #empty() empty layer} then an 799 * empty list is returned. 800 * 801 * @return A possibly-empty unmodifiable list of this layer's parents 802 */ 803 public List<ModuleLayer> parents() { 804 return parents; 805 } 806 807 808 /** 809 * Returns an ordered stream of layers. The first element is this layer, 810 * the remaining elements are the parent layers in DFS order. 811 * 812 * @implNote For now, the assumption is that the number of elements will 813 * be very low and so this method does not use a specialized spliterator. 814 */ 815 Stream<ModuleLayer> layers() { 816 List<ModuleLayer> allLayers = this.allLayers; 817 if (allLayers != null) 818 return allLayers.stream(); 819 820 allLayers = new ArrayList<>(); 821 Set<ModuleLayer> visited = new HashSet<>(); 822 Deque<ModuleLayer> stack = new ArrayDeque<>(); 823 visited.add(this); 824 stack.push(this); 825 826 while (!stack.isEmpty()) { 827 ModuleLayer layer = stack.pop(); 828 allLayers.add(layer); 829 830 // push in reverse order 831 for (int i = layer.parents.size() - 1; i >= 0; i--) { 832 ModuleLayer parent = layer.parents.get(i); 833 if (visited.add(parent)) { 834 stack.push(parent); 835 } 836 } 837 } 838 839 this.allLayers = allLayers = Collections.unmodifiableList(allLayers); 840 return allLayers.stream(); 841 } 842 843 private volatile List<ModuleLayer> allLayers; 844 845 /** 846 * Returns an unmodifiable set of the modules in this layer. 847 * 848 * @return A possibly-empty unmodifiable set of the modules in this layer 849 */ 850 public Set<Module> modules() { 851 Set<Module> modules = this.modules; 852 if (modules == null) { 853 this.modules = modules = Set.copyOf(nameToModule.values()); 854 } 855 return modules; 856 } 857 858 private volatile Set<Module> modules; 859 860 861 /** 862 * Returns the module with the given name in this layer, or if not in this 863 * layer, the {@linkplain #parents() parent} layers. Finding a module in 864 * parent layers is equivalent to invoking {@code findModule} on each 865 * parent, in search order, until the module is found or all parents have 866 * been searched. In a <em>tree of layers</em> then this is equivalent to 867 * a depth-first search. 868 * 869 * @param name 870 * The name of the module to find 871 * 872 * @return The module with the given name or an empty {@code Optional} 873 * if there isn't a module with this name in this layer or any 874 * parent layer 875 */ 876 public Optional<Module> findModule(String name) { 877 Objects.requireNonNull(name); 878 if (this == EMPTY_LAYER) 879 return Optional.empty(); 880 Module m = nameToModule.get(name); 881 if (m != null) 882 return Optional.of(m); 883 884 return layers() 885 .skip(1) // skip this layer 886 .map(l -> l.nameToModule.get(name)) 887 .filter(Objects::nonNull) 888 .findAny(); 889 } 890 891 892 /** 893 * Returns the {@code ClassLoader} for the module with the given name. If 894 * a module of the given name is not in this layer then the {@link #parents() 895 * parent} layers are searched in the manner specified by {@link 896 * #findModule(String) findModule}. 897 * 898 * <p> If there is a security manager then its {@code checkPermission} 899 * method is called with a {@code RuntimePermission("getClassLoader")} 900 * permission to check that the caller is allowed to get access to the 901 * class loader. </p> 902 * 903 * @apiNote This method does not return an {@code Optional<ClassLoader>} 904 * because `null` must be used to represent the bootstrap class loader. 905 * 906 * @param name 907 * The name of the module to find 908 * 909 * @return The ClassLoader that the module is defined to 910 * 911 * @throws IllegalArgumentException if a module of the given name is not 912 * defined in this layer or any parent of this layer 913 * 914 * @throws SecurityException if denied by the security manager 915 */ 916 public ClassLoader findLoader(String name) { 917 Optional<Module> om = findModule(name); 918 919 // can't use map(Module::getClassLoader) as class loader can be null 920 if (om.isPresent()) { 921 return om.get().getClassLoader(); 922 } else { 923 throw new IllegalArgumentException("Module " + name 924 + " not known to this layer"); 925 } 926 } 927 928 /** 929 * Returns a string describing this module layer. 930 * 931 * @return A possibly empty string describing this module layer 932 */ 933 @Override 934 public String toString() { 935 return modules().stream() 936 .map(Module::getName) 937 .collect(Collectors.joining(", ")); 938 } 939 940 /** 941 * Returns the <em>empty</em> layer. There are no modules in the empty 942 * layer. It has no parents. 943 * 944 * @return The empty layer 945 */ 946 public static ModuleLayer empty() { 947 return EMPTY_LAYER; 948 } 949 950 951 /** 952 * Returns the boot layer. The boot layer contains at least one module, 953 * {@code java.base}. Its parent is the {@link #empty() empty} layer. 954 * 955 * @apiNote This method returns {@code null} during startup and before 956 * the boot layer is fully initialized. 957 * 958 * @return The boot layer 959 */ 960 public static ModuleLayer boot() { 961 return System.bootLayer; 962 } 963 964 /** 965 * Returns the ServicesCatalog for this Layer, creating it if not 966 * already created. 967 */ 968 ServicesCatalog getServicesCatalog() { 969 ServicesCatalog servicesCatalog = this.servicesCatalog; 970 if (servicesCatalog != null) 971 return servicesCatalog; 972 973 synchronized (this) { 974 servicesCatalog = this.servicesCatalog; 975 if (servicesCatalog == null) { 976 servicesCatalog = ServicesCatalog.create(); 977 for (Module m : nameToModule.values()) { 978 servicesCatalog.register(m); 979 } 980 this.servicesCatalog = servicesCatalog; 981 } 982 } 983 984 return servicesCatalog; 985 } 986 987 private volatile ServicesCatalog servicesCatalog; 988 989 990 /** 991 * Record that this layer has at least one module defined to the given 992 * class loader. 993 */ 994 void bindToLoader(ClassLoader loader) { 995 // CLV.computeIfAbsent(loader, (cl, clv) -> new CopyOnWriteArrayList<>()) 996 List<ModuleLayer> list = CLV.get(loader); 997 if (list == null) { 998 list = new CopyOnWriteArrayList<>(); 999 List<ModuleLayer> previous = CLV.putIfAbsent(loader, list); 1000 if (previous != null) list = previous; 1001 } 1002 list.add(this); 1003 } 1004 1005 /** 1006 * Returns a stream of the layers that have at least one module defined to 1007 * the given class loader. 1008 */ 1009 static Stream<ModuleLayer> layers(ClassLoader loader) { 1010 List<ModuleLayer> list = CLV.get(loader); 1011 if (list != null) { 1012 return list.stream(); 1013 } else { 1014 return Stream.empty(); 1015 } 1016 } 1017 1018 // the list of layers with modules defined to a class loader 1019 private static final ClassLoaderValue<List<ModuleLayer>> CLV = new ClassLoaderValue<>(); 1020 }