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