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
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.
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");
264 * #defineModulesWithOneLoader(Configuration,List,ClassLoader)
265 * defineModulesWithOneLoader} method when invoked with this layer as the
266 * parent. In other words, if this layer is {@code thisLayer} then this
267 * method is equivalent to invoking:
268 * <pre> {@code
269 * Layer.defineModulesWithOneLoader(cf, List.of(thisLayer), parentLoader).layer();
270 * }</pre>
271 *
272 * @param cf
273 * The configuration for the layer
274 * @param parentLoader
275 * The parent class loader for the class loader created by this
276 * method; may be {@code null} for the bootstrap class loader
277 *
278 * @return The newly created layer
279 *
280 * @throws IllegalArgumentException
281 * If the parent of the given configuration is not the configuration
282 * for this layer
283 * @throws LayerInstantiationException
284 * If all modules cannot be defined to the same class loader for any
285 * of the reasons listed above or the layer cannot be created because
286 * the configuration contains a module named "{@code java.base}" or
287 * a module with a package name starting with "{@code java.}"
288 * @throws SecurityException
289 * If {@code RuntimePermission("createClassLoader")} or
290 * {@code RuntimePermission("getClassLoader")} is denied by
291 * the security manager
292 *
293 * @see #findLoader
294 */
295 public Layer defineModulesWithOneLoader(Configuration cf,
296 ClassLoader parentLoader) {
297 return defineModulesWithOneLoader(cf, List.of(this), parentLoader).layer();
298 }
299
300
301 /**
302 * Creates a new layer, with this layer as its parent, by defining the
303 * modules in the given {@code Configuration} to the Java virtual machine.
304 * Each module is defined to its own {@link ClassLoader} created by this
305 * method. The {@link ClassLoader#getParent() parent} of each class loader
306 * is the given parent class loader. This method works exactly as specified
307 * by the static {@link
308 * #defineModulesWithManyLoaders(Configuration,List,ClassLoader)
309 * defineModulesWithManyLoaders} method when invoked with this layer as the
310 * parent. In other words, if this layer is {@code thisLayer} then this
311 * method is equivalent to invoking:
312 * <pre> {@code
313 * Layer.defineModulesWithManyLoaders(cf, List.of(thisLayer), parentLoader).layer();
314 * }</pre>
315 *
316 * @param cf
317 * The configuration for the layer
318 * @param parentLoader
319 * The parent class loader for each of the class loaders created by
320 * this method; may be {@code null} for the bootstrap class loader
321 *
322 * @return The newly created layer
323 *
324 * @throws IllegalArgumentException
325 * If the parent of the given configuration is not the configuration
326 * for this layer
327 * @throws LayerInstantiationException
328 * If the layer cannot be created because the configuration contains
329 * a module named "{@code java.base}" or a module with a package
330 * name starting with "{@code java.}"
331 * @throws SecurityException
332 * If {@code RuntimePermission("createClassLoader")} or
333 * {@code RuntimePermission("getClassLoader")} is denied by
334 * the security manager
335 *
336 * @see #findLoader
337 */
338 public Layer defineModulesWithManyLoaders(Configuration cf,
339 ClassLoader parentLoader) {
340 return defineModulesWithManyLoaders(cf, List.of(this), parentLoader).layer();
341 }
342
343
344 /**
345 * Creates a new layer, with this layer as its parent, by defining the
346 * modules in the given {@code Configuration} to the Java virtual machine.
347 * Each module is mapped, by name, to its class loader by means of the
348 * given function. This method works exactly as specified by the static
349 * {@link #defineModules(Configuration,List,Function) defineModules}
350 * method when invoked with this layer as the parent. In other words, if
351 * this layer is {@code thisLayer} then this method is equivalent to
352 * invoking:
353 * <pre> {@code
354 * Layer.defineModules(cf, List.of(thisLayer), clf).layer();
355 * }</pre>
356 *
357 * @param cf
358 * The configuration for the layer
359 * @param clf
360 * The function to map a module name to a class loader
361 *
362 * @return The newly created layer
363 *
364 * @throws IllegalArgumentException
365 * If the parent of the given configuration is not the configuration
366 * for this layer
367 * @throws LayerInstantiationException
368 * If creating the {@code Layer} fails for any of the reasons
369 * listed above, the layer cannot be created because the
370 * configuration contains a module named "{@code java.base}",
371 * a module with a package name starting with "{@code java.}" is
372 * mapped to a class loader other than the {@link
373 * ClassLoader#getPlatformClassLoader() platform class loader},
374 * or the function to map a module name to a class loader returns
375 * {@code null}
376 * @throws SecurityException
377 * If {@code RuntimePermission("getClassLoader")} is denied by
378 * the security manager
379 */
380 public Layer defineModules(Configuration cf,
381 Function<String, ClassLoader> clf) {
382 return defineModules(cf, List.of(this), clf).layer();
383 }
384
385 /**
386 * Creates a new layer by defining the modules in the given {@code
387 * Configuration} to the Java virtual machine. This method creates one
388 * class loader and defines all modules to that class loader.
389 *
390 * <p> The class loader created by this method implements <em>direct
391 * delegation</em> when loading types from modules. When its {@link
392 * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
393 * load a class then it uses the package name of the class to map it to a
394 * module. This may be a module in this layer and hence defined to the same
395 * class loader. It may be a package in a module in a parent layer that is
396 * exported to one or more of the modules in this layer. The class
397 * loader delegates to the class loader of the module, throwing {@code
398 * ClassNotFoundException} if not found by that class loader.
399 *
400 * When {@code loadClass} is invoked to load classes that do not map to a
401 * module then it delegates to the parent class loader. </p>
402 *
403 * <p> Attempting to create a layer with all modules defined to the same
404 * class loader can fail for the following reasons:
405 *
406 * <ul>
407 *
408 * <li><p> <em>Overlapping packages</em>: Two or more modules in the
409 * configuration have the same package. </p></li>
410 *
411 * <li><p> <em>Split delegation</em>: The resulting class loader would
412 * need to delegate to more than one class loader in order to load types
413 * in a specific package. </p></li>
414 *
415 * </ul>
416 *
417 * <p> If there is a security manager then the class loader created by
418 * this method will load classes and resources with privileges that are
419 * restricted by the calling context of this method. </p>
420 *
421 * @param cf
422 * The configuration for the layer
423 * @param parentLayers
424 * The list parent layers in search order
425 * @param parentLoader
426 * The parent class loader for the class loader created by this
427 * method; may be {@code null} for the bootstrap class loader
428 *
429 * @return A controller that controls the newly created layer
430 *
431 * @throws IllegalArgumentException
432 * If the parent configurations do not match the configuration of
433 * the parent layers, including order
434 * @throws LayerInstantiationException
435 * If all modules cannot be defined to the same class loader for any
436 * of the reasons listed above or the layer cannot be created because
437 * the configuration contains a module named "{@code java.base}" or
438 * a module with a package name starting with "{@code java.}"
439 * @throws SecurityException
440 * If {@code RuntimePermission("createClassLoader")} or
441 * {@code RuntimePermission("getClassLoader")} is denied by
442 * the security manager
443 *
444 * @see #findLoader
445 */
446 public static Controller defineModulesWithOneLoader(Configuration cf,
447 List<Layer> parentLayers,
448 ClassLoader parentLoader)
449 {
450 List<Layer> parents = new ArrayList<>(parentLayers);
451 checkConfiguration(cf, parents);
452
453 checkCreateClassLoaderPermission();
454 checkGetClassLoaderPermission();
455
456 try {
457 Loader loader = new Loader(cf.modules(), parentLoader);
458 loader.initRemotePackageMap(cf, parents);
463 }
464 }
465
466 /**
467 * Creates a new layer by defining the modules in the given {@code
468 * Configuration} to the Java virtual machine. Each module is defined to
469 * its own {@link ClassLoader} created by this method. The {@link
470 * ClassLoader#getParent() parent} of each class loader is the given parent
471 * class loader.
472 *
473 * <p> The class loaders created by this method implement <em>direct
474 * delegation</em> when loading types from modules. When {@link
475 * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
476 * load a class then it uses the package name of the class to map it to a
477 * module. The package may be in the module defined to the class loader.
478 * The package may be exported by another module in this layer to the
479 * module defined to the class loader. It may be in a package exported by a
480 * module in a parent layer. The class loader delegates to the class loader
481 * of the module, throwing {@code ClassNotFoundException} if not found by
482 * that class loader.
483 *
484 * When {@code loadClass} is invoked to load classes that do not map to a
485 * module then it delegates to the parent class loader. </p>
486 *
487 * <p> If there is a security manager then the class loaders created by
488 * this method will load classes and resources with privileges that are
489 * restricted by the calling context of this method. </p>
490 *
491 * @param cf
492 * The configuration for the layer
493 * @param parentLayers
494 * The list parent layers in search order
495 * @param parentLoader
496 * The parent class loader for each of the class loaders created by
497 * this method; may be {@code null} for the bootstrap class loader
498 *
499 * @return A controller that controls the newly created layer
500 *
501 * @throws IllegalArgumentException
502 * If the parent configurations do not match the configuration of
503 * the parent layers, including order
516 List<Layer> parentLayers,
517 ClassLoader parentLoader)
518 {
519 List<Layer> parents = new ArrayList<>(parentLayers);
520 checkConfiguration(cf, parents);
521
522 checkCreateClassLoaderPermission();
523 checkGetClassLoaderPermission();
524
525 LoaderPool pool = new LoaderPool(cf, parents, parentLoader);
526 try {
527 Layer layer = new Layer(cf, parents, pool::loaderFor);
528 return new Controller(layer);
529 } catch (IllegalArgumentException e) {
530 throw new LayerInstantiationException(e.getMessage());
531 }
532 }
533
534 /**
535 * Creates a new layer by defining the modules in the given {@code
536 * Configuration} to the Java virtual machine.
537 * Each module is mapped, by name, to its class loader by means of the
538 * given function. The class loader delegation implemented by these class
539 * loaders must respect module readability. The class loaders should be
540 * {@link ClassLoader#registerAsParallelCapable parallel-capable} so as to
541 * avoid deadlocks during class loading. In addition, the entity creating
542 * a new layer with this method should arrange that the class loaders are
543 * ready to load from these modules before there are any attempts to load
544 * classes or resources.
545 *
546 * <p> Creating a {@code Layer} can fail for the following reasons: </p>
547 *
548 * <ul>
549 *
550 * <li><p> Two or more modules with the same package are mapped to the
551 * same class loader. </p></li>
552 *
553 * <li><p> A module is mapped to a class loader that already has a
554 * module of the same name defined to it. </p></li>
555 *
556 * <li><p> A module is mapped to a class loader that has already
557 * defined types in any of the packages in the module. </p></li>
558 *
559 * </ul>
560 *
561 * <p> If the function to map a module name to class loader throws an error
562 * or runtime exception then it is propagated to the caller of this method.
563 * </p>
564 *
565 * @apiNote It is implementation specific as to whether creating a Layer
566 * with this method is an atomic operation or not. Consequentially it is
567 * possible for this method to fail with some modules, but not all, defined
568 * to Java virtual machine.
569 *
570 * @param cf
571 * The configuration for the layer
572 * @param parentLayers
573 * The list parent layers in search order
574 * @param clf
575 * The function to map a module name to a class loader
576 *
577 * @return A controller that controls the newly created layer
578 *
579 * @throws IllegalArgumentException
580 * If the parent configurations do not match the configuration of
581 * the parent layers, including order
582 * @throws LayerInstantiationException
583 * If creating the {@code Layer} fails for any of the reasons
584 * listed above, the layer cannot be created because the
585 * configuration contains a module named "{@code java.base}",
586 * a module with a package name starting with "{@code java.}" is
587 * mapped to a class loader other than the {@link
588 * ClassLoader#getPlatformClassLoader() platform class loader},
589 * or the function to map a module name to a class loader returns
590 * {@code null}
591 * @throws SecurityException
592 * If {@code RuntimePermission("getClassLoader")} is denied by
593 * the security manager
594 */
595 public static Controller defineModules(Configuration cf,
596 List<Layer> parentLayers,
597 Function<String, ClassLoader> clf)
598 {
599 List<Layer> parents = new ArrayList<>(parentLayers);
600 checkConfiguration(cf, parents);
601 Objects.requireNonNull(clf);
602
603 checkGetClassLoaderPermission();
604
605 // The boot layer is checked during module system initialization
606 if (boot() != null) {
607 checkForDuplicatePkgs(cf, clf);
608 }
609
610 try {
747
748 this.allLayers = allLayers = Collections.unmodifiableList(allLayers);
749 return allLayers.stream();
750 }
751
752 private volatile List<Layer> allLayers;
753
754 /**
755 * Returns the set of the modules in this layer.
756 *
757 * @return A possibly-empty unmodifiable set of the modules in this layer
758 */
759 public Set<Module> modules() {
760 return Collections.unmodifiableSet(
761 nameToModule.values().stream().collect(Collectors.toSet()));
762 }
763
764
765 /**
766 * Returns the module with the given name in this layer, or if not in this
767 * layer, the {@linkplain #parents parents} layers. Finding a module in
768 * parent layers is equivalent to invoking {@code findModule} on each
769 * parent, in search order, until the module is found or all parents have
770 * been searched. In a <em>tree of layers</em> then this is equivalent to
771 * a depth-first search.
772 *
773 * @param name
774 * The name of the module to find
775 *
776 * @return The module with the given name or an empty {@code Optional}
777 * if there isn't a module with this name in this layer or any
778 * parent layer
779 */
780 public Optional<Module> findModule(String name) {
781 Objects.requireNonNull(name);
782 Module m = nameToModule.get(name);
783 if (m != null)
784 return Optional.of(m);
785
786 return layers()
787 .skip(1) // skip this layer
|
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
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 in a {@link Configuration}
60 * 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 the modules so that the Java virtual machine knows which
63 * module that each class is a member of. </p>
64 *
65 * <p> Creating a layer creates a {@link Module} object for each {@link
66 * ResolvedModule} in the configuration. For each resolved module that is
67 * {@link ResolvedModule#reads() read}, the {@code Module} {@link
68 * Module#canRead reads} the corresponding run-time {@code Module}, which may
69 * be in the same layer or a {@link #parents() parent} layer. The {@code Module}
70 * {@link Module#isExported(String) exports} and {@link Module#isOpen(String)
71 * opens} the packages described by its {@link ModuleDescriptor}. </p>
72 *
73 * <p> The {@link #defineModulesWithOneLoader defineModulesWithOneLoader} and
74 * {@link #defineModulesWithManyLoaders defineModulesWithManyLoaders} methods
75 * provide convenient ways to create a {@code Layer} where all modules are
76 * mapped to a single class loader or where each module is mapped to its own
77 * class loader. The {@link #defineModules defineModules} method is for more
78 * advanced cases where modules are mapped to custom class loaders by means of
79 * a function specified to the method. Each of these methods has an instance
80 * and static variant. The instance methods create a layer with the receiver
81 * as the parent layer. The static methods are for more advanced cases where
82 * there can be more than one parent layer or where a {@link Layer.Controller
83 * Controller} is needed to control modules in the layer. </p>
84 *
85 * <p> A Java virtual machine has at least one non-empty layer, the {@link
86 * #boot() boot} layer, that is created when the Java virtual machine is
87 * started. The boot layer contains module {@code java.base} and is the only
88 * layer in the Java virtual machine with a module named "{@code java.base}".
89 * The modules in the boot layer are mapped to the bootstrap class loader and
90 * other class loaders that are <a href="../ClassLoader.html#builtinLoaders">
91 * built-in</a> into the Java virtual machine. The boot layer will often be
92 * the {@link #parents() parent} when creating additional layers. </p>
93 *
94 * <p> As when creating a {@code Configuration},
95 * {@link ModuleDescriptor#isAutomatic() automatic} modules receive special
96 * treatment when creating a layer. An automatic module is created in the
97 * Java virtual machine as a {@code Module} that reads every unnamed {@code
98 * Module} in the Java virtual machine. </p>
99 *
100 * <p> Unless otherwise specified, passing a {@code null} argument to a method
101 * in this class causes a {@link NullPointerException NullPointerException} to
102 * be thrown. </p>
103 *
104 * <h3> Example usage: </h3>
105 *
106 * <p> This example creates a configuration by resolving a module named
107 * "{@code myapp}" with the configuration for the boot layer as the parent. It
108 * then creates a new layer with the modules in this configuration. All modules
109 * are defined to the same class loader. </p>
110 *
111 * <pre>{@code
112 * ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
113 *
114 * Layer parent = Layer.boot();
115 *
116 * Configuration cf = parent.configuration().resolve(finder, ModuleFinder.of(), Set.of("myapp"));
117 *
118 * ClassLoader scl = ClassLoader.getSystemClassLoader();
119 *
120 * Layer layer = parent.defineModulesWithOneLoader(cf, scl);
121 *
122 * Class<?> c = layer.findLoader("myapp").loadClass("app.Main");
123 * }</pre>
124 *
125 * @since 9
126 * @spec JPMS
127 * @see Module#getLayer()
128 */
129
130 public final class Layer {
131
132 // the empty Layer
133 private static final Layer EMPTY_LAYER
134 = new Layer(Configuration.empty(), List.of(), null);
135
136 // the configuration from which this Layer was created
137 private final Configuration cf;
138
139 // parent layers, empty in the case of the empty layer
140 private final List<Layer> parents;
141
142 // maps module name to jlr.Module
143 private final Map<String, Module> nameToModule;
144
145 /**
146 * Creates a new Layer from the modules in the given configuration.
149 List<Layer> parents,
150 Function<String, ClassLoader> clf)
151 {
152 this.cf = cf;
153 this.parents = parents; // no need to do defensive copy
154
155 Map<String, Module> map;
156 if (parents.isEmpty()) {
157 map = Collections.emptyMap();
158 } else {
159 map = Module.defineModules(cf, clf, this);
160 }
161 this.nameToModule = map; // no need to do defensive copy
162 }
163
164 /**
165 * Controls a layer. The static methods defined by {@link Layer} to create
166 * module layers return a {@code Controller} that can be used to control
167 * modules in the layer.
168 *
169 * <p> Unless otherwise specified, passing a {@code null} argument to a
170 * method in this class causes a {@link NullPointerException
171 * NullPointerException} to be thrown. </p>
172 *
173 * @apiNote Care should be taken with {@code Controller} objects, they
174 * should never be shared with untrusted code.
175 *
176 * @since 9
177 * @spec JPMS
178 */
179 public static final class Controller {
180 private final Layer layer;
181
182 Controller(Layer layer) {
183 this.layer = layer;
184 }
185
186 /**
187 * Returns the layer that this object controls.
188 *
189 * @return the layer
190 */
191 public Layer layer() {
192 return layer;
193 }
194
195 private void ensureInLayer(Module source) {
196 if (!layer.modules().contains(source))
197 throw new IllegalArgumentException(source + " not in layer");
267 * #defineModulesWithOneLoader(Configuration,List,ClassLoader)
268 * defineModulesWithOneLoader} method when invoked with this layer as the
269 * parent. In other words, if this layer is {@code thisLayer} then this
270 * method is equivalent to invoking:
271 * <pre> {@code
272 * Layer.defineModulesWithOneLoader(cf, List.of(thisLayer), parentLoader).layer();
273 * }</pre>
274 *
275 * @param cf
276 * The configuration for the layer
277 * @param parentLoader
278 * The parent class loader for the class loader created by this
279 * method; may be {@code null} for the bootstrap class loader
280 *
281 * @return The newly created layer
282 *
283 * @throws IllegalArgumentException
284 * If the parent of the given configuration is not the configuration
285 * for this layer
286 * @throws LayerInstantiationException
287 * If the layer cannot be created for any of the reasons specified
288 * by the static {@code defineModulesWithOneLoader} method
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 for any of the reasons specified
330 * by the static {@code defineModulesWithManyLoaders} method
331 * @throws SecurityException
332 * If {@code RuntimePermission("createClassLoader")} or
333 * {@code RuntimePermission("getClassLoader")} is denied by
334 * the security manager
335 *
336 * @see #findLoader
337 */
338 public Layer defineModulesWithManyLoaders(Configuration cf,
339 ClassLoader parentLoader) {
340 return defineModulesWithManyLoaders(cf, List.of(this), parentLoader).layer();
341 }
342
343
344 /**
345 * Creates a new layer, with this layer as its parent, by defining the
346 * modules in the given {@code Configuration} to the Java virtual machine.
347 * Each module is mapped, by name, to its class loader by means of the
348 * given function. This method works exactly as specified by the static
349 * {@link #defineModules(Configuration,List,Function) defineModules}
350 * method when invoked with this layer as the parent. In other words, if
351 * this layer is {@code thisLayer} then this method is equivalent to
352 * invoking:
353 * <pre> {@code
354 * Layer.defineModules(cf, List.of(thisLayer), clf).layer();
355 * }</pre>
356 *
357 * @param cf
358 * The configuration for the layer
359 * @param clf
360 * The function to map a module name to a class loader
361 *
362 * @return The newly created layer
363 *
364 * @throws IllegalArgumentException
365 * If the parent of the given configuration is not the configuration
366 * for this layer
367 * @throws LayerInstantiationException
368 * If the layer cannot be created for any of the reasons specified
369 * by the static {@code defineModules} method
370 * @throws SecurityException
371 * If {@code RuntimePermission("getClassLoader")} is denied by
372 * the security manager
373 */
374 public Layer defineModules(Configuration cf,
375 Function<String, ClassLoader> clf) {
376 return defineModules(cf, List.of(this), clf).layer();
377 }
378
379 /**
380 * Creates a new layer by defining the modules in the given {@code
381 * Configuration} to the Java virtual machine. This method creates one
382 * class loader and defines all modules to that class loader.
383 *
384 * <p> The class loader created by this method implements <em>direct
385 * delegation</em> when loading types from modules. When its {@link
386 * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
387 * load a class then it uses the package name of the class to map it to a
388 * module. This may be a module in this layer and hence defined to the same
389 * class loader. It may be a package in a module in a parent layer that is
390 * exported to one or more of the modules in this layer. The class
391 * loader delegates to the class loader of the module, throwing {@code
392 * ClassNotFoundException} if not found by that class loader.
393 * When {@code loadClass} is invoked to load classes that do not map to a
394 * module then it delegates to the parent class loader. </p>
395 *
396 * <p> Attempting to create a layer with all modules defined to the same
397 * class loader can fail for the following reasons:
398 *
399 * <ul>
400 *
401 * <li><p> <em>Overlapping packages</em>: Two or more modules in the
402 * configuration have the same package. </p></li>
403 *
404 * <li><p> <em>Split delegation</em>: The resulting class loader would
405 * need to delegate to more than one class loader in order to load types
406 * in a specific package. </p></li>
407 *
408 * </ul>
409 *
410 * <p> In addition, a layer cannot be created if the configuration contains
411 * a module named "{@code java.base}" or a module with a package name
412 * starting with "{@code java.}". </p>
413 *
414 * <p> If there is a security manager then the class loader created by
415 * this method will load classes and resources with privileges that are
416 * restricted by the calling context of this method. </p>
417 *
418 * @param cf
419 * The configuration for the layer
420 * @param parentLayers
421 * The list parent layers in search order
422 * @param parentLoader
423 * The parent class loader for the class loader created by this
424 * method; may be {@code null} for the bootstrap class loader
425 *
426 * @return A controller that controls the newly created layer
427 *
428 * @throws IllegalArgumentException
429 * If the parent configurations do not match the configuration of
430 * the parent layers, including order
431 * @throws LayerInstantiationException
432 * If all modules cannot be defined to the same class loader for any
433 * of the reasons listed above
434 * @throws SecurityException
435 * If {@code RuntimePermission("createClassLoader")} or
436 * {@code RuntimePermission("getClassLoader")} is denied by
437 * the security manager
438 *
439 * @see #findLoader
440 */
441 public static Controller defineModulesWithOneLoader(Configuration cf,
442 List<Layer> parentLayers,
443 ClassLoader parentLoader)
444 {
445 List<Layer> parents = new ArrayList<>(parentLayers);
446 checkConfiguration(cf, parents);
447
448 checkCreateClassLoaderPermission();
449 checkGetClassLoaderPermission();
450
451 try {
452 Loader loader = new Loader(cf.modules(), parentLoader);
453 loader.initRemotePackageMap(cf, parents);
458 }
459 }
460
461 /**
462 * Creates a new layer by defining the modules in the given {@code
463 * Configuration} to the Java virtual machine. Each module is defined to
464 * its own {@link ClassLoader} created by this method. The {@link
465 * ClassLoader#getParent() parent} of each class loader is the given parent
466 * class loader.
467 *
468 * <p> The class loaders created by this method implement <em>direct
469 * delegation</em> when loading types from modules. When {@link
470 * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
471 * load a class then it uses the package name of the class to map it to a
472 * module. The package may be in the module defined to the class loader.
473 * The package may be exported by another module in this layer to the
474 * module defined to the class loader. It may be in a package exported by a
475 * module in a parent layer. The class loader delegates to the class loader
476 * of the module, throwing {@code ClassNotFoundException} if not found by
477 * that class loader.
478 * When {@code loadClass} is invoked to load classes that do not map to a
479 * module then it delegates to the parent class loader. </p>
480 *
481 * <p> If there is a security manager then the class loaders created by
482 * this method will load classes and resources with privileges that are
483 * restricted by the calling context of this method. </p>
484 *
485 * @param cf
486 * The configuration for the layer
487 * @param parentLayers
488 * The list parent layers in search order
489 * @param parentLoader
490 * The parent class loader for each of the class loaders created by
491 * this method; may be {@code null} for the bootstrap class loader
492 *
493 * @return A controller that controls the newly created layer
494 *
495 * @throws IllegalArgumentException
496 * If the parent configurations do not match the configuration of
497 * the parent layers, including order
510 List<Layer> parentLayers,
511 ClassLoader parentLoader)
512 {
513 List<Layer> parents = new ArrayList<>(parentLayers);
514 checkConfiguration(cf, parents);
515
516 checkCreateClassLoaderPermission();
517 checkGetClassLoaderPermission();
518
519 LoaderPool pool = new LoaderPool(cf, parents, parentLoader);
520 try {
521 Layer layer = new Layer(cf, parents, pool::loaderFor);
522 return new Controller(layer);
523 } catch (IllegalArgumentException e) {
524 throw new LayerInstantiationException(e.getMessage());
525 }
526 }
527
528 /**
529 * Creates a new layer by defining the modules in the given {@code
530 * Configuration} to the Java virtual machine. The given function maps each
531 * module in the configuration, by name, to a class loader. Creating the
532 * layer informs the Java virtual machine about the classes that may be
533 * loaded so that the Java virtual machine knows which module that each
534 * class is a member of.
535 *
536 * <p> The class loader delegation implemented by the class loaders must
537 * respect module readability. The class loaders should be
538 * {@link ClassLoader#registerAsParallelCapable parallel-capable} so as to
539 * avoid deadlocks during class loading. In addition, the entity creating
540 * a new layer with this method should arrange that the class loaders be
541 * ready to load from these modules before there are any attempts to load
542 * classes or resources. </p>
543 *
544 * <p> Creating a {@code Layer} can fail for the following reasons: </p>
545 *
546 * <ul>
547 *
548 * <li><p> Two or more modules with the same package are mapped to the
549 * same class loader. </p></li>
550 *
551 * <li><p> A module is mapped to a class loader that already has a
552 * module of the same name defined to it. </p></li>
553 *
554 * <li><p> A module is mapped to a class loader that has already
555 * defined types in any of the packages in the module. </p></li>
556 *
557 * </ul>
558 *
559 * <p> In addition, a layer cannot be created if the configuration contains
560 * a module named "{@code java.base}", a configuration contains a module
561 * with a package name starting with "{@code java.}" is mapped to a class
562 * loader other than the {@link ClassLoader#getPlatformClassLoader()
563 * platform class loader}, or the function to map a module name to a class
564 * loader returns {@code null}. </p>
565 *
566 * <p> If the function to map a module name to class loader throws an error
567 * or runtime exception then it is propagated to the caller of this method.
568 * </p>
569 *
570 * @apiNote It is implementation specific as to whether creating a Layer
571 * with this method is an atomic operation or not. Consequentially it is
572 * possible for this method to fail with some modules, but not all, defined
573 * to the Java virtual machine.
574 *
575 * @param cf
576 * The configuration for the layer
577 * @param parentLayers
578 * The list parent layers in search order
579 * @param clf
580 * The function to map a module name to a class loader
581 *
582 * @return A controller that controls the newly created layer
583 *
584 * @throws IllegalArgumentException
585 * If the parent configurations do not match the configuration of
586 * the parent layers, including order
587 * @throws LayerInstantiationException
588 * If creating the layer fails for any of the reasons listed above
589 * @throws SecurityException
590 * If {@code RuntimePermission("getClassLoader")} is denied by
591 * the security manager
592 */
593 public static Controller defineModules(Configuration cf,
594 List<Layer> parentLayers,
595 Function<String, ClassLoader> clf)
596 {
597 List<Layer> parents = new ArrayList<>(parentLayers);
598 checkConfiguration(cf, parents);
599 Objects.requireNonNull(clf);
600
601 checkGetClassLoaderPermission();
602
603 // The boot layer is checked during module system initialization
604 if (boot() != null) {
605 checkForDuplicatePkgs(cf, clf);
606 }
607
608 try {
745
746 this.allLayers = allLayers = Collections.unmodifiableList(allLayers);
747 return allLayers.stream();
748 }
749
750 private volatile List<Layer> allLayers;
751
752 /**
753 * Returns the set of the modules in this layer.
754 *
755 * @return A possibly-empty unmodifiable set of the modules in this layer
756 */
757 public Set<Module> modules() {
758 return Collections.unmodifiableSet(
759 nameToModule.values().stream().collect(Collectors.toSet()));
760 }
761
762
763 /**
764 * Returns the module with the given name in this layer, or if not in this
765 * layer, the {@linkplain #parents parent} layers. Finding a module in
766 * parent layers is equivalent to invoking {@code findModule} on each
767 * parent, in search order, until the module is found or all parents have
768 * been searched. In a <em>tree of layers</em> then this is equivalent to
769 * a depth-first search.
770 *
771 * @param name
772 * The name of the module to find
773 *
774 * @return The module with the given name or an empty {@code Optional}
775 * if there isn't a module with this name in this layer or any
776 * parent layer
777 */
778 public Optional<Module> findModule(String name) {
779 Objects.requireNonNull(name);
780 Module m = nameToModule.get(name);
781 if (m != null)
782 return Optional.of(m);
783
784 return layers()
785 .skip(1) // skip this layer
|