public final class Configuration extends Object
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 requires
clauses.
The dependence graph is augmented with edges that take account of
implicitly declared dependences (requires transitive
) to create a
readability graph. A Configuration
encapsulates the
resulting graph of resolved modules
.
Suppose we have the following observable modules:
module m1 { requires m2; }
module m2 { requires transitive m3; }
module m3 { }
module m4 { }
If the module m1
is resolved then the resulting configuration
contains three modules (m1
, m2
, m3
). The edges in
its readability graph are:
m1 --> m2 (meaning m1 reads m2)
m1 --> m3
m2 --> m3
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 relative configuration 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.
Suppose we have the following observable modules:
module m1 { requires m2; requires java.xml; }
module m2 { }
If module m1
is resolved with the configuration for the boot
layer as the parent then the resulting
configuration contains two modules (m1
, m2
). The edges in
its readability graph are:
m1 --> m2
m1 --> java.xml
where module java.xml
is in the parent configuration. For
simplicity, this example omits the implicitly declared dependence on the
java.base
module.
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 requires transitive
all other automatic modules in the configuration (and all automatic modules
in parent configurations).
Service binding is the process of augmenting a graph of resolved modules
from the set of observable modules induced by the service-use dependence
(uses
and 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.
Suppose we have the following observable modules:
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 { }
If the module m1
is resolved then the resulting graph of modules
has one module (m1
). If the graph is augmented with modules induced
by the service-use dependence relation then the configuration will contain
four modules (m1
, m2
, m3
, m4
). The edges in
its readability graph are:
m2 --> m1
m3 --> m1
m3 --> m4
The edges in the conceptual service-use graph are:
m1 --> m2 (meaning m1 uses a service that is provided by m2)
m1 --> m3
If this configuration is instantiated as a Layer
, and if code in
module m1
uses ServiceLoader
to
iterate over implementations of p.S.class
, then it will iterate over
an instance of p2.S2
and p3.S3
.
The following example uses the resolveRequires
method to resolve
a module named myapp 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.
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(", ")));
});
Layer
Modifier and Type | Method | Description |
---|---|---|
static Configuration |
empty() |
Returns the empty configuration.
|
Optional<ResolvedModule> |
findModule(String name) |
Finds a resolved module in this configuration, or if not in this
configuration, the parent configurations.
|
Set<ResolvedModule> |
modules() |
Returns an immutable set of the resolved modules in this configuration.
|
List<Configuration> |
parents() |
Returns an unmodifiable list of this configuration's parents, in search
order.
|
Configuration |
resolveRequires(ModuleFinder before,
ModuleFinder after,
Collection<String> roots) |
Resolves a collection of root modules, with this configuration as its
parent, to create a new configuration.
|
static Configuration |
resolveRequires(ModuleFinder before,
List<Configuration> parents,
ModuleFinder after,
Collection<String> roots) |
Resolves a collection of root modules to create a configuration.
|
Configuration |
resolveRequiresAndUses(ModuleFinder before,
ModuleFinder after,
Collection<String> roots) |
Resolves a collection of root modules, with service binding, and with
this configuration as its parent, to create a new configuration.
|
static Configuration |
resolveRequiresAndUses(ModuleFinder before,
List<Configuration> parents,
ModuleFinder after,
Collection<String> roots) |
Resolves a collection of root modules, with service binding, to create
configuration.
|
String |
toString() |
Returns a string describing this configuration.
|
public Configuration resolveRequires(ModuleFinder before, ModuleFinder after, Collection<String> roots)
resolveRequires
method when invoked with this configuration as the parent. In other words,
if this configuration is cf
then this method is equivalent to
invoking:
Configuration.resolveRequires(before, List.of(cf), after, roots);
before
- The before module finder to find modulesafter
- The after module finder to locate modules when a
module cannot be located by the before
module finder
and the module is not in this configurationroots
- The possibly-empty collection of module names of the modules
to resolveResolutionException
- If resolution or the post-resolution checks failSecurityException
- If locating a module is denied by the security managerpublic Configuration resolveRequiresAndUses(ModuleFinder before, ModuleFinder after, Collection<String> roots)
resolveRequiresAndUses
method when invoked with this configuration
as the parent. In other words, if this configuration is cf
then
this method is equivalent to invoking:
Configuration.resolveRequiresAndUses(before, List.of(cf), after, roots);
before
- The before module finder to find modulesafter
- The after module finder to locate modules when not
located by the before
module finder and this
configurationroots
- The possibly-empty collection of module names of the modules
to resolveResolutionException
- If resolution or the post-resolution checks failSecurityException
- If locating a module is denied by the security managerpublic static Configuration resolveRequires(ModuleFinder before, List<Configuration> parents, ModuleFinder after, Collection<String> roots)
Each root module is located using the given before
module
finder. If a module is not found then it is located in the parent
configuration as if by invoking the findModule
method on each parent in iteration order. If not found then
the module is located using the given after
module finder. The
same search order is used to locate transitive dependences. Root modules
or dependences that are located in a parent configuration are resolved
no further and are not included in the resulting configuration.
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.
Resolution and the (post-resolution) consistency checks may fail for following reasons:
A root module, or a direct or transitive dependency, is not found.
An error occurs when attempting to find a module.
Possible errors include I/O errors, errors detected parsing a module
descriptor (module-info.class
) or two versions of the same
module are found in the same directory.
A cycle is detected, say where module m1
requires
module m2
and m2
requires m1
.
Two or more modules in the configuration export the same
package to a module that reads both. This includes the case where a
module M
containing package p
reads another module
that exports p
to M
.
A module M
declares that it "uses p.S
" or
"provides p.S with ...
" but package p
is neither in
module M
nor exported to M
by any module that
M
reads.
A module M
declares that it
"provides ... with q.T
" but package q
is not in
module M
.
Two or more modules in the configuration are specific to
different operating systems
,
architectures
, or versions
.
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.
before
- The before module finder to find modulesparents
- The list parent configurations in search orderafter
- The after module finder to locate modules when not
located by the before
module finder or in parent
configurationsroots
- The possibly-empty collection of module names of the modules
to resolveResolutionException
- If resolution or the post-resolution checks failIllegalArgumentException
- If the list of parents is emptySecurityException
- If locating a module is denied by the security managerpublic static Configuration resolveRequiresAndUses(ModuleFinder before, List<Configuration> parents, ModuleFinder after, Collection<String> roots)
This method works exactly as specified by resolveRequires
except that the graph of resolved modules is augmented
with modules induced by the service-use dependence relation.
More specifically, the root modules are resolved as if by calling
resolveRequires
. The resolved modules, and all modules in the
parent configurations, with service
dependences
are then examined. All modules found by the given module
finders that 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
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.
As service binding involves resolution then it may fail with ResolutionException
for exactly the same reasons specified in
resolveRequires
.
before
- The before module finder to find modulesparents
- The list parent configurations in search orderafter
- The after module finder to locate modules when not
located by the before
module finder or in parent
configurationsroots
- The possibly-empty collection of module names of the modules
to resolveResolutionException
- If resolution or the post-resolution checks failIllegalArgumentException
- If the list of parents is emptySecurityException
- If locating a module is denied by the security managerpublic static Configuration empty()
public List<Configuration> parents()
public Set<ResolvedModule> modules()
public Optional<ResolvedModule> findModule(String name)
findModule
on each parent, in search order, until the module
is found or all parents have been searched. In a tree of
configurations then this is equivalent to a depth-first search.name
- The module name of the resolved module to find
Optional
if there isn't a module with this name in this
configuration or any parent configurations Submit a bug or feature
For further API reference and developer documentation, see Java SE Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples.
Copyright © 1993, 2017, Oracle and/or its affiliates. 500 Oracle Parkway
Redwood Shores, CA 94065 USA. All rights reserved.
DRAFT 9-Debian+0-9b155-1