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