< prev index next >
src/java.base/share/classes/java/lang/module/Configuration.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 40,179 ****
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
! * The configuration that is the result of resolution or resolution with
! * service binding.
! *
! * <h2><a name="resolution">Resolution</a></h2>
! *
! * <p> Resolution is the process of computing the transitive closure of a set
! * of root modules over a set of observable modules by resolving the
! * dependences expressed by {@code requires} clauses.
! *
! * The <em>dependence graph</em> is augmented with edges that take account of
! * implicitly declared dependences ({@code requires transitive}) to create a
! * <em>readability graph</em>. A {@code Configuration} encapsulates the
! * resulting graph of {@link ResolvedModule resolved modules}.
! *
! * <p> Suppose we have the following observable modules: </p>
! * <pre> {@code
! * module m1 { requires m2; }
! * module m2 { requires transitive m3; }
! * module m3 { }
! * module m4 { }
! * } </pre>
! *
! * <p> If the module {@code m1} is resolved then the resulting configuration
! * contains three modules ({@code m1}, {@code m2}, {@code m3}). The edges in
! * its readability graph are: </p>
! * <pre> {@code
! * m1 --> m2 (meaning m1 reads m2)
! * m1 --> m3
! * m2 --> m3
! * } </pre>
! *
! * <p> Resolution is an additive process. When computing the transitive closure
! * then the dependence relation may include dependences on modules in parent
! * configurations. The result is a <em>relative configuration</em> that is
! * relative to one or more parent configurations and where the readability graph
! * may have edges from modules in the configuration to modules in parent
! * configurations.
! *
! * </p>
! *
! * <p> Suppose we have the following observable modules: </p>
! * <pre> {@code
! * module m1 { requires m2; requires java.xml; }
! * module m2 { }
! * } </pre>
! *
! * <p> If module {@code m1} is resolved with the configuration for the {@link
! * java.lang.reflect.Layer#boot() boot} layer as the parent then the resulting
! * configuration contains two modules ({@code m1}, {@code m2}). The edges in
! * its readability graph are:
! * <pre> {@code
! * m1 --> m2
! * m1 --> java.xml
! * } </pre>
! * where module {@code java.xml} is in the parent configuration. For
! * simplicity, this example omits the implicitly declared dependence on the
! * {@code java.base} module.
! *
! * <a name="automaticmoduleresolution"></a>
! * <p> {@link ModuleDescriptor#isAutomatic() Automatic} modules receive special
! * treatment during resolution. Each automatic module is resolved so that it
! * reads all other modules in the configuration and all parent configurations.
! * Each automatic module is also resolved as if it {@code requires transitive}
! * all other automatic modules in the configuration (and all automatic modules
! * in parent configurations). </p>
!
! * <h2><a name="servicebinding">Service binding</a></h2>
! *
! * <p> Service binding is the process of augmenting a graph of resolved modules
! * from the set of observable modules induced by the service-use dependence
! * ({@code uses} and {@code provides} clauses). Any module that was not
! * previously in the graph requires resolution to compute its transitive
! * closure. Service binding is an iterative process in that adding a module
! * that satisfies some service-use dependence may introduce new service-use
! * dependences. </p>
! *
! * <p> Suppose we have the following observable modules: </p>
! * <pre> {@code
! * module m1 { exports p; uses p.S; }
! * module m2 { requires m1; provides p.S with p2.S2; }
! * module m3 { requires m1; requires m4; provides p.S with p3.S3; }
! * module m4 { }
! * } </pre>
! *
! * <p> If the module {@code m1} is resolved then the resulting graph of modules
! * has one module ({@code m1}). If the graph is augmented with modules induced
! * by the service-use dependence relation then the configuration will contain
! * four modules ({@code m1}, {@code m2}, {@code m3}, {@code m4}). The edges in
! * its readability graph are: </p>
! * <pre> {@code
! * m2 --> m1
! * m3 --> m1
! * m3 --> m4
! * } </pre>
! * <p> The edges in the conceptual service-use graph are: </p>
! * <pre> {@code
! * m1 --> m2 (meaning m1 uses a service that is provided by m2)
! * m1 --> m3
! * } </pre>
! *
! * <p> If this configuration is instantiated as a {@code Layer}, and if code in
! * module {@code m1} uses {@link java.util.ServiceLoader ServiceLoader} to
! * iterate over implementations of {@code p.S.class}, then it will iterate over
! * an instance of {@code p2.S2} and {@code p3.S3}. </p>
*
* <h3> Example </h3>
*
! * <p> The following example uses the {@code resolveRequires} method to resolve
! * a module named <em>myapp</em> with the configuration for the boot layer as
! * the parent configuration. It prints the name of each resolved module and
! * the names of the modules that each module reads. </p>
*
* <pre>{@code
* ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
*
* Configuration parent = Layer.boot().configuration();
*
! * Configuration cf = parent.resolveRequires(finder,
! * ModuleFinder.of(),
! * Set.of("myapp"));
* cf.modules().forEach(m -> {
* System.out.format("%s -> %s%n",
* m.name(),
* m.reads().stream()
* .map(ResolvedModule::name)
* .collect(Collectors.joining(", ")));
* });
* }</pre>
*
* @since 9
* @see java.lang.reflect.Layer
*/
public final class Configuration {
// @see Configuration#empty()
--- 40,102 ----
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
! * A configuration that is the result of <a href="package-summary.html#resolution">
! * resolution</a> or resolution with <a href="package-summary.html#servicebinding">
! * service binding</a>.
! *
! * <p> A configuration encapsulates the <em>readability graph</em> that is the
! * output of resolution. A readability graph is a directed graph where the nodes
! * are of type {@link ResolvedModule} and the edges represent the readability
! * amongst the modules. {@code Configuration} defines the {@link #modules()
! * modules()} method to get the set of resolved modules in the graph. {@code
! * ResolvedModule} defines the {@link ResolvedModule#reads() reads()} method to
! * get the set of modules that a resolved module reads. The modules that are
! * read may be in the same configuration or may be in {@link #parents() parent}
! * configurations. </p>
! *
! * <p> Configuration defines the {@link #resolve(ModuleFinder,List,ModuleFinder,Collection)
! * resolve} method to resolve a collection of root modules, and the {@link
! * #resolveAndBind(ModuleFinder,List,ModuleFinder,Collection) resolveAndBind}
! * method to do resolution with service binding. There are instance and
! * static variants of both methods. The instance methods create a configuration
! * with the receiver as the parent configuration. The static methods are for
! * more advanced cases where there can be more than one parent configuration. </p>
! *
! * <p> Each {@link java.lang.reflect.Layer layer} of modules in the Java virtual
! * machine is created from a configuration. The configuration for the {@link
! * java.lang.reflect.Layer#boot() boot} layer is obtained by invoking {@code
! * Layer.boot().configuration()}. The configuration for the boot layer will
! * often be the parent when creating new configurations. </p>
*
* <h3> Example </h3>
*
! * <p> The following example uses the {@link
! * #resolve(ModuleFinder,ModuleFinder,Collection) resolve} method to resolve a
! * module named <em>myapp</em> with the configuration for the boot layer as the
! * parent configuration. It prints the name of each resolved module and the
! * names of the modules that each module reads. </p>
*
* <pre>{@code
* ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
*
* Configuration parent = Layer.boot().configuration();
*
! * Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("myapp"));
* cf.modules().forEach(m -> {
* System.out.format("%s -> %s%n",
* m.name(),
* m.reads().stream()
* .map(ResolvedModule::name)
* .collect(Collectors.joining(", ")));
* });
* }</pre>
*
* @since 9
+ * @spec JPMS
* @see java.lang.reflect.Layer
*/
public final class Configuration {
// @see Configuration#empty()
*** 184,198 ****
--- 107,133 ----
private final Map<ResolvedModule, Set<ResolvedModule>> graph;
private final Set<ResolvedModule> modules;
private final Map<String, ResolvedModule> nameToModule;
+ // module constraints on target
+ private final String osName;
+ private final String osArch;
+ private final String osVersion;
+
+ String osName() { return osName; }
+ String osArch() { return osArch; }
+ String osVersion() { return osVersion; }
+
private Configuration() {
this.parents = Collections.emptyList();
this.graph = Collections.emptyMap();
this.modules = Collections.emptySet();
this.nameToModule = Collections.emptyMap();
+ this.osName = null;
+ this.osArch = null;
+ this.osVersion = null;
}
private Configuration(List<Configuration> parents,
Resolver resolver,
boolean check)
*** 212,316 ****
this.parents = Collections.unmodifiableList(parents);
this.graph = g;
this.modules = Set.of(moduleArray);
this.nameToModule = Map.ofEntries(nameEntries);
- }
/**
* Resolves a collection of root modules, with this configuration as its
* parent, to create a new configuration. This method works exactly as
* specified by the static {@link
! * #resolveRequires(ModuleFinder,List,ModuleFinder,Collection) resolveRequires}
* method when invoked with this configuration as the parent. In other words,
* if this configuration is {@code cf} then this method is equivalent to
* invoking:
* <pre> {@code
! * Configuration.resolveRequires(before, List.of(cf), after, roots);
* }</pre>
*
* @param before
* The <em>before</em> module finder to find modules
* @param after
! * The <em>after</em> module finder to locate modules when a
! * module cannot be located by the {@code before} module finder
! * and the module is not in this configuration
* @param roots
* The possibly-empty collection of module names of the modules
* to resolve
*
* @return The configuration that is the result of resolving the given
* root modules
*
* @throws ResolutionException
! * If resolution or the post-resolution checks fail
* @throws SecurityException
* If locating a module is denied by the security manager
*/
! public Configuration resolveRequires(ModuleFinder before,
ModuleFinder after,
Collection<String> roots)
{
! return resolveRequires(before, List.of(this), after, roots);
}
/**
* Resolves a collection of root modules, with service binding, and with
* this configuration as its parent, to create a new configuration.
* This method works exactly as specified by the static {@link
! * #resolveRequiresAndUses(ModuleFinder,List,ModuleFinder,Collection)
! * resolveRequiresAndUses} method when invoked with this configuration
* as the parent. In other words, if this configuration is {@code cf} then
* this method is equivalent to invoking:
* <pre> {@code
! * Configuration.resolveRequiresAndUses(before, List.of(cf), after, roots);
* }</pre>
*
*
* @param before
* The <em>before</em> module finder to find modules
* @param after
* The <em>after</em> module finder to locate modules when not
! * located by the {@code before} module finder and this
! * configuration
* @param roots
* The possibly-empty collection of module names of the modules
* to resolve
*
! * @return The configuration that is the result of resolving the given
! * root modules
*
* @throws ResolutionException
! * If resolution or the post-resolution checks fail
* @throws SecurityException
* If locating a module is denied by the security manager
*/
! public Configuration resolveRequiresAndUses(ModuleFinder before,
ModuleFinder after,
Collection<String> roots)
{
! return resolveRequiresAndUses(before, List.of(this), after, roots);
}
/**
* Resolves a collection of root modules, with service binding, and with
* the empty configuration as its parent. The post resolution checks
* are optionally run.
*
* This method is used to create the configuration for the boot layer.
*/
! static Configuration resolveRequiresAndUses(ModuleFinder finder,
Collection<String> roots,
boolean check,
PrintStream traceOutput)
{
List<Configuration> parents = List.of(empty());
Resolver resolver = new Resolver(finder, parents, ModuleFinder.of(), traceOutput);
! resolver.resolveRequires(roots).resolveUses();
return new Configuration(parents, resolver, check);
}
--- 147,262 ----
this.parents = Collections.unmodifiableList(parents);
this.graph = g;
this.modules = Set.of(moduleArray);
this.nameToModule = Map.ofEntries(nameEntries);
+ this.osName = resolver.osName();
+ this.osArch = resolver.osArch();
+ this.osVersion = resolver.osVersion();
+ }
/**
* Resolves a collection of root modules, with this configuration as its
* parent, to create a new configuration. This method works exactly as
* specified by the static {@link
! * #resolve(ModuleFinder,List,ModuleFinder,Collection) resolve}
* method when invoked with this configuration as the parent. In other words,
* if this configuration is {@code cf} then this method is equivalent to
* invoking:
* <pre> {@code
! * Configuration.resolve(before, List.of(cf), after, roots);
* }</pre>
*
* @param before
* The <em>before</em> module finder to find modules
* @param after
! * The <em>after</em> module finder to locate modules when not
! * located by the {@code before} module finder or in parent
! * configurations
* @param roots
* The possibly-empty collection of module names of the modules
* to resolve
*
* @return The configuration that is the result of resolving the given
* root modules
*
+ * @throws FindException
+ * If resolution fails for any of the observability-related reasons
+ * specified by the static {@code resolve} method
* @throws ResolutionException
! * If any of the post-resolution consistency checks specified by
! * the static {@code resolve} method fail
* @throws SecurityException
* If locating a module is denied by the security manager
*/
! public Configuration resolve(ModuleFinder before,
ModuleFinder after,
Collection<String> roots)
{
! return resolve(before, List.of(this), after, roots);
}
/**
* Resolves a collection of root modules, with service binding, and with
* this configuration as its parent, to create a new configuration.
* This method works exactly as specified by the static {@link
! * #resolveAndBind(ModuleFinder,List,ModuleFinder,Collection)
! * resolveAndBind} method when invoked with this configuration
* as the parent. In other words, if this configuration is {@code cf} then
* this method is equivalent to invoking:
* <pre> {@code
! * Configuration.resolveAndBind(before, List.of(cf), after, roots);
* }</pre>
*
*
* @param before
* The <em>before</em> module finder to find modules
* @param after
* The <em>after</em> module finder to locate modules when not
! * located by the {@code before} module finder or in parent
! * configurations
* @param roots
* The possibly-empty collection of module names of the modules
* to resolve
*
! * @return The configuration that is the result of resolving, with service
! * binding, the given root modules
*
+ * @throws FindException
+ * If resolution fails for any of the observability-related reasons
+ * specified by the static {@code resolve} method
* @throws ResolutionException
! * If any of the post-resolution consistency checks specified by
! * the static {@code resolve} method fail
* @throws SecurityException
* If locating a module is denied by the security manager
*/
! public Configuration resolveAndBind(ModuleFinder before,
ModuleFinder after,
Collection<String> roots)
{
! return resolveAndBind(before, List.of(this), after, roots);
}
/**
* Resolves a collection of root modules, with service binding, and with
* the empty configuration as its parent. The post resolution checks
* are optionally run.
*
* This method is used to create the configuration for the boot layer.
*/
! static Configuration resolveAndBind(ModuleFinder finder,
Collection<String> roots,
boolean check,
PrintStream traceOutput)
{
List<Configuration> parents = List.of(empty());
Resolver resolver = new Resolver(finder, parents, ModuleFinder.of(), traceOutput);
! resolver.resolve(roots).bind();
return new Configuration(parents, resolver, check);
}
*** 326,350 ****
* or dependences that are located in a parent configuration are resolved
* no further and are not included in the resulting configuration. </p>
*
* <p> When all modules have been resolved then the resulting dependency
* graph is checked to ensure that it does not contain cycles. A
! * readability graph is constructed and in conjunction with the module
* exports and service use, checked for consistency. </p>
*
! * <p> Resolution and the (post-resolution) consistency checks may fail for
! * following reasons: </p>
*
* <ul>
* <li><p> A root module, or a direct or transitive dependency, is not
* found. </p></li>
*
* <li><p> An error occurs when attempting to find a module.
* Possible errors include I/O errors, errors detected parsing a module
* descriptor ({@code module-info.class}) or two versions of the same
* module are found in the same directory. </p></li>
*
* <li><p> A cycle is detected, say where module {@code m1} requires
* module {@code m2} and {@code m2} requires {@code m1}. </p></li>
*
* <li><p> Two or more modules in the configuration export the same
* package to a module that reads both. This includes the case where a
--- 272,310 ----
* or dependences that are located in a parent configuration are resolved
* no further and are not included in the resulting configuration. </p>
*
* <p> When all modules have been resolved then the resulting dependency
* graph is checked to ensure that it does not contain cycles. A
! * readability graph is constructed, and in conjunction with the module
* exports and service use, checked for consistency. </p>
*
! * <p> Resolution may fail with {@code FindException} for the following
! * <em>observability-related</em> reasons: </p>
*
* <ul>
* <li><p> A root module, or a direct or transitive dependency, is not
* found. </p></li>
*
* <li><p> An error occurs when attempting to find a module.
* Possible errors include I/O errors, errors detected parsing a module
* descriptor ({@code module-info.class}) or two versions of the same
* module are found in the same directory. </p></li>
*
+ * <li><p> A module with the required name is found but the module
+ * requires a different {@link ModuleDescriptor#osName() operating
+ * system}, {@link ModuleDescriptor#osArch() architecture}, or {@link
+ * ModuleDescriptor#osVersion() version} to other modules that have
+ * been resolved for the new configuration or modules in the parent
+ * configurations. </p></li>
+ *
+ * </ul>
+ *
+ * <p> Post-resolution consistency checks may fail with {@code
+ * ResolutionException} for the following reasons: </p>
+ *
+ * <ul>
+ *
* <li><p> A cycle is detected, say where module {@code m1} requires
* module {@code m2} and {@code m2} requires {@code m1}. </p></li>
*
* <li><p> Two or more modules in the configuration export the same
* package to a module that reads both. This includes the case where a
*** 354,378 ****
* <li><p> A module {@code M} declares that it "{@code uses p.S}" or
* "{@code provides p.S with ...}" but package {@code p} is neither in
* module {@code M} nor exported to {@code M} by any module that
* {@code M} reads. </p></li>
*
- * <li><p> A module {@code M} declares that it
- * "{@code provides ... with q.T}" but package {@code q} is not in
- * module {@code M}. </p></li>
- *
- * <li><p> Two or more modules in the configuration are specific to
- * different {@link ModuleDescriptor#osName() operating systems},
- * {@link ModuleDescriptor#osArch() architectures}, or {@link
- * ModuleDescriptor#osVersion() versions}. </p></li>
- *
- * <li><p> Other implementation specific checks, for example referential
- * integrity checks to ensure that different versions of tighly coupled
- * modules cannot be combined in the same configuration. </p></li>
- *
* </ul>
*
* @param before
* The <em>before</em> module finder to find modules
* @param parents
* The list parent configurations in search order
* @param after
--- 314,329 ----
* <li><p> A module {@code M} declares that it "{@code uses p.S}" or
* "{@code provides p.S with ...}" but package {@code p} is neither in
* module {@code M} nor exported to {@code M} by any module that
* {@code M} reads. </p></li>
*
* </ul>
*
+ * @implNote In the implementation then observability of modules may depend
+ * on referential integrity checks that ensure that different builds of
+ * tightly coupled modules cannot be combined in the same configuration.
+ *
* @param before
* The <em>before</em> module finder to find modules
* @param parents
* The list parent configurations in search order
* @param after
*** 384,401 ****
* to resolve
*
* @return The configuration that is the result of resolving the given
* root modules
*
* @throws ResolutionException
! * If resolution or the post-resolution checks fail
* @throws IllegalArgumentException
! * If the list of parents is empty
* @throws SecurityException
* If locating a module is denied by the security manager
*/
! public static Configuration resolveRequires(ModuleFinder before,
List<Configuration> parents,
ModuleFinder after,
Collection<String> roots)
{
Objects.requireNonNull(before);
--- 335,357 ----
* to resolve
*
* @return The configuration that is the result of resolving the given
* root modules
*
+ * @throws FindException
+ * If resolution fails for an observability-related reason
* @throws ResolutionException
! * If a post-resolution consistency checks fails
* @throws IllegalArgumentException
! * If the list of parents is empty, or the list has two or more
! * parents with modules for different target operating systems,
! * architectures, or versions
! *
* @throws SecurityException
* If locating a module is denied by the security manager
*/
! public static Configuration resolve(ModuleFinder before,
List<Configuration> parents,
ModuleFinder after,
Collection<String> roots)
{
Objects.requireNonNull(before);
*** 405,442 ****
List<Configuration> parentList = new ArrayList<>(parents);
if (parentList.isEmpty())
throw new IllegalArgumentException("'parents' is empty");
Resolver resolver = new Resolver(before, parentList, after, null);
! resolver.resolveRequires(roots);
return new Configuration(parentList, resolver, true);
}
/**
* Resolves a collection of root modules, with service binding, to create
* configuration.
*
* <p> This method works exactly as specified by {@link
! * #resolveRequires(ModuleFinder,List,ModuleFinder,Collection)
! * resolveRequires} except that the graph of resolved modules is augmented
* with modules induced by the service-use dependence relation. </p>
*
* <p> More specifically, the root modules are resolved as if by calling
! * {@code resolveRequires}. The resolved modules, and all modules in the
* parent configurations, with {@link ModuleDescriptor#uses() service
* dependences} are then examined. All modules found by the given module
* finders that {@link ModuleDescriptor#provides() provide} an
* implementation of one or more of the service types are added to the
* module graph and then resolved as if by calling the {@code
! * resolveRequires} method. Adding modules to the module graph may
! * introduce new service-use dependences and so the process works
! * iteratively until no more modules are added. </p>
! *
! * <p> As service binding involves resolution then it may fail with {@link
! * ResolutionException} for exactly the same reasons specified in
! * {@code resolveRequires}. </p>
*
* @param before
* The <em>before</em> module finder to find modules
* @param parents
* The list parent configurations in search order
--- 361,398 ----
List<Configuration> parentList = new ArrayList<>(parents);
if (parentList.isEmpty())
throw new IllegalArgumentException("'parents' is empty");
Resolver resolver = new Resolver(before, parentList, after, null);
! resolver.resolve(roots);
return new Configuration(parentList, resolver, true);
}
/**
* Resolves a collection of root modules, with service binding, to create
* configuration.
*
* <p> This method works exactly as specified by {@link
! * #resolve(ModuleFinder,List,ModuleFinder,Collection)
! * resolve} except that the graph of resolved modules is augmented
* with modules induced by the service-use dependence relation. </p>
*
* <p> More specifically, the root modules are resolved as if by calling
! * {@code resolve}. The resolved modules, and all modules in the
* parent configurations, with {@link ModuleDescriptor#uses() service
* dependences} are then examined. All modules found by the given module
* finders that {@link ModuleDescriptor#provides() provide} an
* implementation of one or more of the service types are added to the
* module graph and then resolved as if by calling the {@code
! * resolve} method. Adding modules to the module graph may introduce new
! * service-use dependences and so the process works iteratively until no
! * more modules are added. </p>
! *
! * <p> As service binding involves resolution then it may fail with {@code
! * FindException} or {@code ResolutionException} for exactly the same
! * reasons specified in {@code resolve}. </p>
*
* @param before
* The <em>before</em> module finder to find modules
* @param parents
* The list parent configurations in search order
*** 446,466 ****
* configurations
* @param roots
* The possibly-empty collection of module names of the modules
* to resolve
*
! * @return The configuration that is the result of resolving the given
! * root modules
*
* @throws ResolutionException
! * If resolution or the post-resolution checks fail
* @throws IllegalArgumentException
! * If the list of parents is empty
* @throws SecurityException
* If locating a module is denied by the security manager
*/
! public static Configuration resolveRequiresAndUses(ModuleFinder before,
List<Configuration> parents,
ModuleFinder after,
Collection<String> roots)
{
Objects.requireNonNull(before);
--- 402,428 ----
* configurations
* @param roots
* The possibly-empty collection of module names of the modules
* to resolve
*
! * @return The configuration that is the result of resolving, with service
! * binding, the given root modules
*
+ * @throws FindException
+ * If resolution fails for any of the observability-related reasons
+ * specified by the static {@code resolve} method
* @throws ResolutionException
! * If any of the post-resolution consistency checks specified by
! * the static {@code resolve} method fail
* @throws IllegalArgumentException
! * If the list of parents is empty, or the list has two or more
! * parents with modules for different target operating systems,
! * architectures, or versions
* @throws SecurityException
* If locating a module is denied by the security manager
*/
! public static Configuration resolveAndBind(ModuleFinder before,
List<Configuration> parents,
ModuleFinder after,
Collection<String> roots)
{
Objects.requireNonNull(before);
*** 470,480 ****
List<Configuration> parentList = new ArrayList<>(parents);
if (parentList.isEmpty())
throw new IllegalArgumentException("'parents' is empty");
Resolver resolver = new Resolver(before, parentList, after, null);
! resolver.resolveRequires(roots).resolveUses();
return new Configuration(parentList, resolver, true);
}
--- 432,442 ----
List<Configuration> parentList = new ArrayList<>(parents);
if (parentList.isEmpty())
throw new IllegalArgumentException("'parents' is empty");
Resolver resolver = new Resolver(before, parentList, after, null);
! resolver.resolve(roots).bind();
return new Configuration(parentList, resolver, true);
}
< prev index next >