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. 311 * 312 * @param target 313 * The module to update 314 * 315 * @return This controller 316 * 317 * @throws IllegalArgumentException 318 * If {@code target} is not in the module layer 319 * 320 * @throws IllegalCallerException 321 * If the caller is in a module that does not have native access enabled 322 * 323 * @since 22 324 */ 325 @CallerSensitive 326 @Restricted 327 public Controller enableNativeAccess(Module target) { 328 ensureInLayer(target); 329 Reflection.ensureNativeAccess(Reflection.getCallerClass(), Module.class, 330 "enableNativeAccess"); 331 target.implAddEnableNativeAccess(); 332 return this; 333 } 334 } 335 336 337 /** 338 * Creates a new module layer, with this layer as its parent, by defining the 339 * modules in the given {@code Configuration} to the Java virtual machine. 340 * This method creates one class loader and defines all modules to that 341 * class loader. The {@link ClassLoader#getParent() parent} of each class 342 * loader is the given parent class loader. This method works exactly as 343 * specified by the static {@link 344 * #defineModulesWithOneLoader(Configuration,List,ClassLoader) 345 * defineModulesWithOneLoader} method when invoked with this layer as the 346 * parent. In other words, if this layer is {@code thisLayer} then this 347 * method is equivalent to invoking: 348 * <pre> {@code 349 * ModuleLayer.defineModulesWithOneLoader(cf, List.of(thisLayer), parentLoader).layer(); 350 * }</pre> 351 * 352 * @param cf 353 * The configuration for the layer 354 * @param parentLoader 355 * The parent class loader for the class loader created by this 356 * method; may be {@code null} for the bootstrap class loader 357 * 358 * @return The newly created layer 359 * 360 * @throws IllegalArgumentException 361 * If the given configuration has more than one parent or the parent 362 * of the configuration is not the configuration for this layer 363 * @throws LayerInstantiationException 364 * If the layer cannot be created for any of the reasons specified 365 * by the static {@code defineModulesWithOneLoader} method 366 * @throws SecurityException 367 * If {@code RuntimePermission("createClassLoader")} or 368 * {@code RuntimePermission("getClassLoader")} is denied by 369 * the security manager 370 * 371 * @see #findLoader 372 */ 373 public ModuleLayer defineModulesWithOneLoader(Configuration cf, 374 ClassLoader parentLoader) { 375 return defineModulesWithOneLoader(cf, List.of(this), parentLoader).layer(); 376 } 377 378 379 /** 380 * Creates a new module layer, with this layer as its parent, by defining the 381 * modules in the given {@code Configuration} to the Java virtual machine. 382 * Each module is defined to its own {@link ClassLoader} created by this 383 * method. The {@link ClassLoader#getParent() parent} of each class loader 384 * is the given parent class loader. This method works exactly as specified 385 * by the static {@link 386 * #defineModulesWithManyLoaders(Configuration,List,ClassLoader) 387 * defineModulesWithManyLoaders} method when invoked with this layer as the 388 * parent. In other words, if this layer is {@code thisLayer} then this 389 * method is equivalent to invoking: 390 * <pre> {@code 391 * ModuleLayer.defineModulesWithManyLoaders(cf, List.of(thisLayer), parentLoader).layer(); 392 * }</pre> 393 * 394 * @param cf 395 * The configuration for the layer 396 * @param parentLoader 397 * The parent class loader for each of the class loaders created by 398 * this method; may be {@code null} for the bootstrap class loader 399 * 400 * @return The newly created layer 401 * 402 * @throws IllegalArgumentException 403 * If the given configuration has more than one parent or the parent 404 * of the configuration is not the configuration for this layer 405 * @throws LayerInstantiationException 406 * If the layer cannot be created for any of the reasons specified 407 * by the static {@code defineModulesWithManyLoaders} method 408 * @throws SecurityException 409 * If {@code RuntimePermission("createClassLoader")} or 410 * {@code RuntimePermission("getClassLoader")} is denied by 411 * the security manager 412 * 413 * @see #findLoader 414 */ 415 public ModuleLayer defineModulesWithManyLoaders(Configuration cf, 416 ClassLoader parentLoader) { 417 return defineModulesWithManyLoaders(cf, List.of(this), parentLoader).layer(); 418 } 419 420 421 /** 422 * Creates a new module layer, with this layer as its parent, by defining the 423 * modules in the given {@code Configuration} to the Java virtual machine. 424 * Each module is mapped, by name, to its class loader by means of the 425 * given function. This method works exactly as specified by the static 426 * {@link #defineModules(Configuration,List,Function) defineModules} 427 * method when invoked with this layer as the parent. In other words, if 428 * this layer is {@code thisLayer} then this method is equivalent to 429 * invoking: 430 * <pre> {@code 431 * ModuleLayer.defineModules(cf, List.of(thisLayer), clf).layer(); 432 * }</pre> 433 * 434 * @param cf 435 * The configuration for the layer 436 * @param clf 437 * The function to map a module name to a class loader 438 * 439 * @return The newly created layer 440 * 441 * @throws IllegalArgumentException 442 * If the given configuration has more than one parent or the parent 443 * of the configuration is not the configuration for this layer 444 * @throws LayerInstantiationException 445 * If the layer cannot be created for any of the reasons specified 446 * by the static {@code defineModules} method 447 * @throws SecurityException 448 * If {@code RuntimePermission("getClassLoader")} is denied by 449 * the security manager 450 */ 451 public ModuleLayer defineModules(Configuration cf, 452 Function<String, ClassLoader> clf) { 453 return defineModules(cf, List.of(this), clf).layer(); 454 } 455 456 /** 457 * Creates a new module layer by defining the modules in the given {@code 458 * Configuration} to the Java virtual machine. This method creates one 459 * class loader and defines all modules to that class loader. 460 * 461 * <p> The class loader created by this method implements <em>direct 462 * delegation</em> when loading classes from modules. If the {@link 463 * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to 464 * load a class then it uses the package name of the class to map it to a 465 * module. This may be a module in this layer and hence defined to the same 466 * class loader. It may be a package in a module in a parent layer that is 467 * exported to one or more of the modules in this layer. The class 468 * loader delegates to the class loader of the module, throwing {@code 469 * ClassNotFoundException} if not found by that class loader. 470 * When {@code loadClass} is invoked to load classes that do not map to a 471 * module then it delegates to the parent class loader. </p> 472 * 473 * <p> The class loader created by this method locates resources 474 * ({@link ClassLoader#getResource(String) getResource}, {@link 475 * ClassLoader#getResources(String) getResources}, and other resource 476 * methods) in all modules in the layer before searching the parent class 477 * loader. </p> 478 * 479 * <p> Attempting to create a layer with all modules defined to the same 480 * class loader can fail for the following reasons: 481 * 482 * <ul> 483 * 484 * <li><p> <em>Overlapping packages</em>: Two or more modules in the 485 * configuration have the same package. </p></li> 486 * 487 * <li><p> <em>Split delegation</em>: The resulting class loader would 488 * need to delegate to more than one class loader in order to load 489 * classes in a specific package. </p></li> 490 * 491 * </ul> 492 * 493 * <p> In addition, a layer cannot be created if the configuration contains 494 * a module named "{@code java.base}", or a module contains a package named 495 * "{@code java}" or a package with a name starting with "{@code java.}". </p> 496 * 497 * <p> If there is a security manager then the class loader created by 498 * this method will load classes and resources with privileges that are 499 * restricted by the calling context of this method. </p> 500 * 501 * @param cf 502 * The configuration for the layer 503 * @param parentLayers 504 * The list of parent layers in search order 505 * @param parentLoader 506 * The parent class loader for the class loader created by this 507 * method; may be {@code null} for the bootstrap class loader 508 * 509 * @return A controller that controls the newly created layer 510 * 511 * @throws IllegalArgumentException 512 * If the parent(s) of the given configuration do not match the 513 * configuration of the parent layers, including order 514 * @throws LayerInstantiationException 515 * If all modules cannot be defined to the same class loader for any 516 * of the reasons listed above 517 * @throws SecurityException 518 * If {@code RuntimePermission("createClassLoader")} or 519 * {@code RuntimePermission("getClassLoader")} is denied by 520 * the security manager 521 * 522 * @see #findLoader 523 */ 524 public static Controller defineModulesWithOneLoader(Configuration cf, 525 List<ModuleLayer> parentLayers, 526 ClassLoader parentLoader) 527 { 528 List<ModuleLayer> parents = List.copyOf(parentLayers); 529 checkConfiguration(cf, parents); 530 531 checkCreateClassLoaderPermission(); 532 checkGetClassLoaderPermission(); 533 534 try { 535 Loader loader = new Loader(cf.modules(), parentLoader); 536 loader.initRemotePackageMap(cf, parents); 537 ModuleLayer layer = new ModuleLayer(cf, parents, mn -> loader); 538 return new Controller(layer); 539 } catch (IllegalArgumentException | IllegalStateException e) { 540 throw new LayerInstantiationException(e.getMessage()); 541 } 542 } 543 544 /** 545 * Creates a new module layer by defining the modules in the given {@code 546 * Configuration} to the Java virtual machine. Each module is defined to 547 * its own {@link ClassLoader} created by this method. The {@link 548 * ClassLoader#getParent() parent} of each class loader is the given parent 549 * class loader. 550 * 551 * <p> The class loaders created by this method implement <em>direct 552 * delegation</em> when loading classes from modules. If the {@link 553 * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to 554 * load a class then it uses the package name of the class to map it to a 555 * module. The package may be in the module defined to the class loader. 556 * The package may be exported by another module in this layer to the 557 * module defined to the class loader. It may be in a package exported by a 558 * module in a parent layer. The class loader delegates to the class loader 559 * of the module, throwing {@code ClassNotFoundException} if not found by 560 * that class loader. When {@code loadClass} is invoked to load a class 561 * that does not map to a module then it delegates to the parent class 562 * loader. </p> 563 * 564 * <p> The class loaders created by this method locate resources 565 * ({@link ClassLoader#getResource(String) getResource}, {@link 566 * ClassLoader#getResources(String) getResources}, and other resource 567 * methods) in the module defined to the class loader before searching 568 * the parent class loader. </p> 569 * 570 * <p> If there is a security manager then the class loaders created by 571 * this method will load classes and resources with privileges that are 572 * restricted by the calling context of this method. </p> 573 * 574 * @param cf 575 * The configuration for the layer 576 * @param parentLayers 577 * The list of parent layers in search order 578 * @param parentLoader 579 * The parent class loader for each of the class loaders created by 580 * this method; may be {@code null} for the bootstrap class loader 581 * 582 * @return A controller that controls the newly created layer 583 * 584 * @throws IllegalArgumentException 585 * If the parent(s) of the given configuration do not match the 586 * configuration of the parent layers, including order 587 * @throws LayerInstantiationException 588 * If the layer cannot be created because the configuration contains 589 * a module named "{@code java.base}" or a module contains a package 590 * named "{@code java}" or a package with a name starting with 591 * "{@code java.}" 592 * 593 * @throws SecurityException 594 * If {@code RuntimePermission("createClassLoader")} or 595 * {@code RuntimePermission("getClassLoader")} is denied by 596 * the security manager 597 * 598 * @see #findLoader 599 */ 600 public static Controller defineModulesWithManyLoaders(Configuration cf, 601 List<ModuleLayer> parentLayers, 602 ClassLoader parentLoader) 603 { 604 List<ModuleLayer> parents = List.copyOf(parentLayers); 605 checkConfiguration(cf, parents); 606 607 checkCreateClassLoaderPermission(); 608 checkGetClassLoaderPermission(); 609 610 LoaderPool pool = new LoaderPool(cf, parents, parentLoader); 611 try { 612 ModuleLayer layer = new ModuleLayer(cf, parents, pool::loaderFor); 613 return new Controller(layer); 614 } catch (IllegalArgumentException | IllegalStateException e) { 615 throw new LayerInstantiationException(e.getMessage()); 616 } 617 } 618 619 /** 620 * Creates a new module layer by defining the modules in the given {@code 621 * Configuration} to the Java virtual machine. The given function maps each 622 * module in the configuration, by name, to a class loader. Creating the 623 * layer informs the Java virtual machine about the classes that may be 624 * loaded so that the Java virtual machine knows which module that each 625 * class is a member of. 626 * 627 * <p> The class loader delegation implemented by the class loaders must 628 * respect module readability. The class loaders should be 629 * {@link ClassLoader#registerAsParallelCapable parallel-capable} so as to 630 * avoid deadlocks during class loading. In addition, the entity creating 631 * a new layer with this method should arrange that the class loaders be 632 * ready to load from these modules before there are any attempts to load 633 * classes or resources. </p> 634 * 635 * <p> Creating a layer can fail for the following reasons: </p> 636 * 637 * <ul> 638 * 639 * <li><p> Two or more modules with the same package are mapped to the 640 * same class loader. </p></li> 641 * 642 * <li><p> A module is mapped to a class loader that already has a 643 * module of the same name defined to it. </p></li> 644 * 645 * <li><p> A module is mapped to a class loader that has already 646 * defined types in any of the packages in the module. </p></li> 647 * 648 * </ul> 649 * 650 * <p> In addition, a layer cannot be created if the configuration contains 651 * a module named "{@code java.base}", a configuration contains a module 652 * with a package named "{@code java}" or a package name starting with 653 * "{@code java.}", or the function to map a module name to a class loader 654 * returns {@code null} or the {@linkplain ClassLoader#getPlatformClassLoader() 655 * platform class loader}. </p> 656 * 657 * <p> If the function to map a module name to class loader throws an error 658 * or runtime exception then it is propagated to the caller of this method. 659 * </p> 660 * 661 * @apiNote It is implementation specific as to whether creating a layer 662 * with this method is an atomic operation or not. Consequently it is 663 * possible for this method to fail with some modules, but not all, defined 664 * to the Java virtual machine. 665 * 666 * @param cf 667 * The configuration for the layer 668 * @param parentLayers 669 * The list of parent layers in search order 670 * @param clf 671 * The function to map a module name to a class loader 672 * 673 * @return A controller that controls the newly created layer 674 * 675 * @throws IllegalArgumentException 676 * If the parent(s) of the given configuration do not match the 677 * configuration of the parent layers, including order 678 * @throws LayerInstantiationException 679 * If creating the layer fails for any of the reasons listed above 680 * @throws SecurityException 681 * If {@code RuntimePermission("getClassLoader")} is denied by 682 * the security manager 683 */ 684 public static Controller defineModules(Configuration cf, 685 List<ModuleLayer> parentLayers, 686 Function<String, ClassLoader> clf) 687 { 688 List<ModuleLayer> parents = List.copyOf(parentLayers); 689 checkConfiguration(cf, parents); 690 Objects.requireNonNull(clf); 691 692 checkGetClassLoaderPermission(); 693 694 // The boot layer is checked during module system initialization 695 if (boot() != null) { 696 checkForDuplicatePkgs(cf, clf); 697 } 698 699 try { 700 ModuleLayer layer = new ModuleLayer(cf, parents, clf); 701 return new Controller(layer); 702 } catch (IllegalArgumentException | IllegalStateException e) { 703 throw new LayerInstantiationException(e.getMessage()); 704 } 705 } 706 707 708 /** 709 * Checks that the parent configurations match the configuration of 710 * the parent layers. 711 */ 712 private static void checkConfiguration(Configuration cf, 713 List<ModuleLayer> parentLayers) 714 { 715 Objects.requireNonNull(cf); 716 717 List<Configuration> parentConfigurations = cf.parents(); 718 if (parentLayers.size() != parentConfigurations.size()) 719 throw new IllegalArgumentException("wrong number of parents"); 720 721 int index = 0; 722 for (ModuleLayer parent : parentLayers) { 723 if (parent.configuration() != parentConfigurations.get(index)) { 724 throw new IllegalArgumentException( 725 "Parent of configuration != configuration of this Layer"); 726 } 727 index++; 728 } 729 } 730 731 private static void checkCreateClassLoaderPermission() { 732 @SuppressWarnings("removal") 733 SecurityManager sm = System.getSecurityManager(); 734 if (sm != null) 735 sm.checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION); 736 } 737 738 private static void checkGetClassLoaderPermission() { 739 @SuppressWarnings("removal") 740 SecurityManager sm = System.getSecurityManager(); 741 if (sm != null) 742 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); 743 } 744 745 /** 746 * Checks a configuration and the module-to-loader mapping to ensure that 747 * no two modules mapped to the same class loader have the same package. 748 * It also checks that no two automatic modules have the same package. 749 * 750 * @throws LayerInstantiationException 751 */ 752 private static void checkForDuplicatePkgs(Configuration cf, 753 Function<String, ClassLoader> clf) 754 { 755 // HashMap allows null keys 756 Map<ClassLoader, Set<String>> loaderToPackages = new HashMap<>(); 757 for (ResolvedModule resolvedModule : cf.modules()) { 758 ModuleDescriptor descriptor = resolvedModule.reference().descriptor(); 759 ClassLoader loader = clf.apply(descriptor.name()); 760 761 Set<String> loaderPackages 762 = loaderToPackages.computeIfAbsent(loader, k -> new HashSet<>()); 763 764 for (String pkg : descriptor.packages()) { 765 boolean added = loaderPackages.add(pkg); 766 if (!added) { 767 throw fail("More than one module with package %s mapped" + 768 " to the same class loader", pkg); 769 } 770 } 771 } 772 } 773 774 /** 775 * Creates a LayerInstantiationException with the message formatted from 776 * the given format string and arguments. 777 */ 778 private static LayerInstantiationException fail(String fmt, Object ... args) { 779 String msg = String.format(fmt, args); 780 return new LayerInstantiationException(msg); 781 } 782 783 784 /** 785 * Returns the configuration for this layer. 786 * 787 * @return The configuration for this layer 788 */ 789 public Configuration configuration() { 790 return cf; 791 } 792 793 /** 794 * Returns an unmodifiable list of this layer's parents, in search 795 * order. If this is the {@linkplain #empty() empty layer} then an 796 * empty list is returned. 797 * 798 * @return A possibly-empty unmodifiable list of this layer's parents 799 */ 800 public List<ModuleLayer> parents() { 801 return parents; 802 } 803 804 805 /** 806 * Returns an ordered stream of layers. The first element is this layer, 807 * the remaining elements are the parent layers in DFS order. 808 * 809 * @implNote For now, the assumption is that the number of elements will 810 * be very low and so this method does not use a specialized spliterator. 811 */ 812 Stream<ModuleLayer> layers() { 813 List<ModuleLayer> allLayers = this.allLayers; 814 if (allLayers != null) 815 return allLayers.stream(); 816 817 allLayers = new ArrayList<>(); 818 Set<ModuleLayer> visited = new HashSet<>(); 819 Deque<ModuleLayer> stack = new ArrayDeque<>(); 820 visited.add(this); 821 stack.push(this); 822 823 while (!stack.isEmpty()) { 824 ModuleLayer layer = stack.pop(); 825 allLayers.add(layer); 826 827 // push in reverse order 828 for (int i = layer.parents.size() - 1; i >= 0; i--) { 829 ModuleLayer parent = layer.parents.get(i); 830 if (visited.add(parent)) { 831 stack.push(parent); 832 } 833 } 834 } 835 836 this.allLayers = allLayers = Collections.unmodifiableList(allLayers); 837 return allLayers.stream(); 838 } 839 840 private volatile List<ModuleLayer> allLayers; 841 842 /** 843 * Returns an unmodifiable set of the modules in this layer. 844 * 845 * @return A possibly-empty unmodifiable set of the modules in this layer 846 */ 847 public Set<Module> modules() { 848 Set<Module> modules = this.modules; 849 if (modules == null) { 850 this.modules = modules = Set.copyOf(nameToModule.values()); 851 } 852 return modules; 853 } 854 855 private volatile Set<Module> modules; 856 857 858 /** 859 * Returns the module with the given name in this layer, or if not in this 860 * layer, the {@linkplain #parents() parent} layers. Finding a module in 861 * parent layers is equivalent to invoking {@code findModule} on each 862 * parent, in search order, until the module is found or all parents have 863 * been searched. In a <em>tree of layers</em> then this is equivalent to 864 * a depth-first search. 865 * 866 * @param name 867 * The name of the module to find 868 * 869 * @return The module with the given name or an empty {@code Optional} 870 * if there isn't a module with this name in this layer or any 871 * parent layer 872 */ 873 public Optional<Module> findModule(String name) { 874 Objects.requireNonNull(name); 875 if (this == EMPTY_LAYER) 876 return Optional.empty(); 877 Module m = nameToModule.get(name); 878 if (m != null) 879 return Optional.of(m); 880 881 return layers() 882 .skip(1) // skip this layer 883 .map(l -> l.nameToModule.get(name)) 884 .filter(Objects::nonNull) 885 .findAny(); 886 } 887 888 889 /** 890 * Returns the {@code ClassLoader} for the module with the given name. If 891 * a module of the given name is not in this layer then the {@link #parents() 892 * parent} layers are searched in the manner specified by {@link 893 * #findModule(String) findModule}. 894 * 895 * <p> If there is a security manager then its {@code checkPermission} 896 * method is called with a {@code RuntimePermission("getClassLoader")} 897 * permission to check that the caller is allowed to get access to the 898 * class loader. </p> 899 * 900 * @apiNote This method does not return an {@code Optional<ClassLoader>} 901 * because `null` must be used to represent the bootstrap class loader. 902 * 903 * @param name 904 * The name of the module to find 905 * 906 * @return The ClassLoader that the module is defined to 907 * 908 * @throws IllegalArgumentException if a module of the given name is not 909 * defined in this layer or any parent of this layer 910 * 911 * @throws SecurityException if denied by the security manager 912 */ 913 public ClassLoader findLoader(String name) { 914 Optional<Module> om = findModule(name); 915 916 // can't use map(Module::getClassLoader) as class loader can be null 917 if (om.isPresent()) { 918 return om.get().getClassLoader(); 919 } else { 920 throw new IllegalArgumentException("Module " + name 921 + " not known to this layer"); 922 } 923 } 924 925 /** 926 * Returns a string describing this module layer. 927 * 928 * @return A possibly empty string describing this module layer 929 */ 930 @Override 931 public String toString() { 932 return modules().stream() 933 .map(Module::getName) 934 .collect(Collectors.joining(", ")); 935 } 936 937 /** 938 * Returns the <em>empty</em> layer. There are no modules in the empty 939 * layer. It has no parents. 940 * 941 * @return The empty layer 942 */ 943 public static ModuleLayer empty() { 944 return EMPTY_LAYER; 945 } 946 947 948 /** 949 * Returns the boot layer. The boot layer contains at least one module, 950 * {@code java.base}. Its parent is the {@link #empty() empty} layer. 951 * 952 * @apiNote This method returns {@code null} during startup and before 953 * the boot layer is fully initialized. 954 * 955 * @return The boot layer 956 */ 957 public static ModuleLayer boot() { 958 return System.bootLayer; 959 } 960 961 /** 962 * Returns the ServicesCatalog for this Layer, creating it if not 963 * already created. 964 */ 965 ServicesCatalog getServicesCatalog() { 966 ServicesCatalog servicesCatalog = this.servicesCatalog; 967 if (servicesCatalog != null) 968 return servicesCatalog; 969 970 synchronized (this) { 971 servicesCatalog = this.servicesCatalog; 972 if (servicesCatalog == null) { 973 servicesCatalog = ServicesCatalog.create(); 974 for (Module m : nameToModule.values()) { 975 servicesCatalog.register(m); 976 } 977 this.servicesCatalog = servicesCatalog; 978 } 979 } 980 981 return servicesCatalog; 982 } 983 984 private volatile ServicesCatalog servicesCatalog; 985 986 987 /** 988 * Record that this layer has at least one module defined to the given 989 * class loader. 990 */ 991 void bindToLoader(ClassLoader loader) { 992 // CLV.computeIfAbsent(loader, (cl, clv) -> new CopyOnWriteArrayList<>()) 993 List<ModuleLayer> list = CLV.get(loader); 994 if (list == null) { 995 list = new CopyOnWriteArrayList<>(); 996 List<ModuleLayer> previous = CLV.putIfAbsent(loader, list); 997 if (previous != null) list = previous; 998 } 999 list.add(this); 1000 } 1001 1002 /** 1003 * Returns a stream of the layers that have at least one module defined to 1004 * the given class loader. 1005 */ 1006 static Stream<ModuleLayer> layers(ClassLoader loader) { 1007 List<ModuleLayer> list = CLV.get(loader); 1008 if (list != null) { 1009 return list.stream(); 1010 } else { 1011 return Stream.empty(); 1012 } 1013 } 1014 1015 // the list of layers with modules defined to a class loader 1016 private static final ClassLoaderValue<List<ModuleLayer>> CLV = new ClassLoaderValue<>(); 1017 }