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 */
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
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 */
210 public ModuleLayer layer() {
211 return layer;
212 }
213
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
695 private static void checkCreateClassLoaderPermission() {
696 SecurityManager sm = System.getSecurityManager();
697 if (sm != null)
698 sm.checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);
699 }
700
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
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 */
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 */
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 */
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 */
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 */
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