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