Package java.lang.module


packagejava.lang.module
Classes to support module descriptors and creating configurations of modulesby means of resolution and service binding.

Unless otherwise noted, passing anull argument to a constructoror method of any class or interface in this package will cause aNullPointerException to be thrown. Additionally,invoking a method with an array or collection containing anull elementwill cause aNullPointerException, unless otherwise specified.

Module Resolution

Resolution is the process of computing how modules depend on each other.The process occurs at compile time and run time.

Resolution is a two-step process. The first step recursively enumeratesthe 'requires' directives of a set of root modules. If all the enumeratedmodules are observable, then the second step computes their readability graph.The readability graph embodies how modules depend on each other, which inturn controls access across module boundaries.

Step 1: Recursive enumeration

Recursive enumeration takes a set of module names, looks up each of theirmodule declarations, and for each module declaration, recursively enumerates:

  • the module names given by the 'requires' directives with the 'transitive' modifier, and

  • at the discretion of the host system, the module names given by the 'requires' directives without the 'transitive' modifier.

Module declarations are looked up in a set of observable modules. The setof observable modules is determined in an implementation specific manner. Theset of observable modules may include modules with explicit declarations(that is, with amodule-info.java source file ormodule-info.classfile) and modules with implicit declarations (that is,automatic modules).Because an automatic module has no explicit module declaration, it has no'requires' directives of its own, although its name may be given by a'requires' directive of an explicit module declaration.

The set of root modules, whose names are the initial input to thisalgorithm, is determined in an implementation specific manner. The set ofroot modules may include automatic modules.

If at least one automatic module is enumerated by this algorithm, thenevery observable automatic module must be enumerated, regardless of whetherany of their names are given by 'requires' directives of explicit moduledeclarations.

If any of the following conditions occur, then resolution fails:

  • Any root module is not observable.

  • Any module whose name is given by a 'requires' directive with the 'transitive' modifier is not observable.

  • At the discretion of the host system, any module whose name is given by a 'requires' directive without the 'transitive' modifier is not observable.

  • The algorithm in this step enumerates the same module name twice. This indicates a cycle in the 'requires' directives, disregarding any 'transitive' modifiers.

Otherwise, resolution proceeds to step 2.

Step 2: Computing the readability graph

A 'requires' directive (irrespective of 'transitive') expresses thatone module depends on some other module. The effect of the 'transitive'modifier is to cause additional modules to also depend on the other module.If module M 'requires transitive N', then not only does M depend on N, butany module that depends on M also depends on N. This allows M to berefactored so that some or all of its content can be moved to a new module Nwithout breaking modules that have a 'requires M' directive.

Module dependencies are represented by the readability graph. Thereadability graph is a directed graph whose vertices are the modulesenumerated in step 1 and whose edges represent readability between pairs ofmodules. The edges are specified as follows:

First, readability is determined by the 'requires' directives of theenumerated modules, disregarding any 'transitive' modifiers:

  • For each enumerated module A that 'requires' B: A "reads" B.

  • For each enumerated module X that is automatic: X "reads" every other enumerated module (it is "as if" an automatic module has 'requires' directives for every other enumerated module).

Second, readability is augmented to account for 'transitive' modifiers:

  • For each enumerated module A that "reads" B:

    • If B 'requires transitive' C, then A "reads" C as well as B. This augmentation is recursive: since A "reads" C, if C 'requires transitive' D, then A "reads" D as well as C and B.

    • If B is an automatic module, then A "reads" every other enumerated automatic module. (It is "as if" an automatic module has 'requires transitive' directives for every other enumerated automatic module).

Finally, every module "reads" itself.

If any of the following conditions occur in the readability graph, thenresolution fails:

  • A module "reads" two or more modules with the same name. This includes the case where a module "reads" another with the same name as itself.

  • Two or more modules export a package with the same name 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".

Otherwise, resolution succeeds, and the result of resolution is thereadability graph.

Root modules

The set of root modules at compile-time is usually the set of modulesbeing compiled. At run-time, the set of root modules is usually theapplication module specified to the 'java' launcher. When compiling code inthe unnamed module, or at run-time when the main application class is loadedfrom the class path, then the default set of root modules is implementationspecific. In the JDK the default set of root modules contains every module onthe upgrade module path or among the system modules that exports at least onepackage, without qualification.

Observable modules

The set of observable modules at both compile-time and run-time isdetermined by searching several different paths, and also by searchingthe compiled modules built in to the environment. The search order is asfollows:

  1. At compile time only, the compilation module path. This path contains module definitions in source form.

  2. The upgrade module path. This path contains compiled definitions of modules that will be observed in preference to the compiled definitions of anyupgradeable modules that are present in (3) and (4). See the Java SE Platform for the designation of which standard modules are upgradeable.

  3. The system modules, which are the compiled definitions built in to the environment.

  4. The application module path. This path contains compiled definitions of library and application modules.

'requires' directives with 'static' modifier

'requires' directives that have the 'static' modifier express an optionaldependence at run time. If a module declares that it 'requires static M' thenresolution does not search the observable modules for M to satisfy the dependency.However, if M is recursively enumerated at step 1 then all modules that areenumerated and `requires static M` will read M.

TheOptionalServices section ofConfiguration shows how resolutioncan be resilient when a service comes from a module that is optional at run time.

Completeness

Resolution may be partial at compile-time in that the complete transitiveclosure may not be required to compile a set of modules. Minimally, thereadability graph that is constructed and validated at compile-time includesthe modules being compiled, their direct dependences, and all implicitlydeclared dependences (requires transitive).

At run-time, resolution is an additive process. The recursive enumerationat step 1 may be relative to previous resolutions so that a root module,or a module named in a 'requires' directive, is not enumerated when it wasenumerated by a previous (or parent) resolution. The readability graph thatis the result of resolution may therefore have a vertex for a module enumeratedin step 1 but with an edge to represent that the module reads a module thatwas enumerated by previous (or parent) resolution.

Since:
9