Mark Reinhold
jpms-spec-comments@openjdk.java.net
This specification defines the Java Platform Module System.
The goal of this specification, as stated in the JSR, is to define an approachable yet scalable module system for the Java Platform. It must be approachable, i.e., easy to learn and easy to use, so that developers can use it to construct and maintain their own libraries, frameworks, and applications. It must be scalable so that it can be used to modularize the Java SE Platform itself, and its implementations.
This specification achieves that goal by providing two fundamental capabilities:
Reliable configuration, to replace the brittle, error-prone class-path mechanism with a means for program components to declare explicit dependences upon one another, along with
Strong encapsulation, to allow a component to declare which of its public types are accessible to other components, and which are not.
These capabilities are realized by treating modules as a fundamental new kind of program component that is defined by a construct of the Java programming language and interpreted uniformly at both compile time and run time.
This specification contains:
Annotated versions of the Java SE 9 Editions of the Java Language Specification (JLS) and the Java Virtual Machine Specification (JVMS), in which change bars and dark blue text indicate additions and modifications for the module system. (Unrelated changes for Java SE 9 are red for addition and bright blue for modification.)
A summary of changes to the JLS and the JVMS in support of module declarations, along with a summary of changes to align the entire JLS and JVMS with the module system.
Changes to the Java SE Platform API Specification, and the detailed differences. (The detailed differences contain a few changes that are unrelated to this specification but impractical to omit; in case of conflict the API specification is authoritative.)
Changes to the JAR File Specification.
Changes to the Java Native Interface Specification (JNI).
Changes to the JVM Tool Interface Specification (JVM TI).
Changes to the Java Debug Wire Protocol (JDWP).
Related external documents which may be of interest include:
The issue summary, which documents the history and status of all issues raised, considered, and resolved.
A design overview, which as of this writing is slightly out of date in some of the more advanced details but is nonetheless a useful overview of the essential concepts.
These two documents are cited for information only; they are not part of this specification.
This specification intentionally leaves some features and capabilities to future releases, when there will be more time to work out the specification and implementation details and when there is more practical experience with the module system to inform choices which at this point are difficult to make. Several potential topics for future exploration are enumerated here, in a rough decreasing order of priority, for the benefit of those who will evolve this specification going forward.
Avoid concealed-package conflicts Make it easy to load modules, without using reflection, when they contain non-exported packages of the same name.
The simplest way to provide this capability is to load modules that contain conflicting packages into their own class loaders. This approach may seem simple on the surface but it raises numerous design and implementation issues that require careful investigation, so a specific solution is left to a future release.
The impact of leaving this to a future release is ameliorated by two factors: The chances of package-name conflicts are reduced by the near-universal use of the reversed Internet domain-name convention for package names, and there are already effective—if somewhat crude—techniques for coping with conflicting packages, namely shading and shadowing.
Cyclic module relationships Allow cyclic relationships amongst modules at run time, though not at compile time.
The arguments for forbidding cyclic relationships are that this restriction makes the module graph easier to reason about, it simplifies the module system itself, and that, philosophically, any modules involved in a cycle are logically one module anyway, so they should be defined as such in the first place in order to guide developers toward better design practices. (For further discussion see Kirk Knoernschild’s book, Java Application Architecture, §4.4, “Cyclic Dependencies—The Death Knell.”)
The argument for allowing cyclic relationships, at least at run time, is based on real-world experience with large applications assembled from many unrelated components. In such systems it is possible for cyclic relationships to arise unexpectedly, especially as the application evolves over time. It is useful to be able to accommodate such cycles, if only temporarily, since removing them can be costly or impractical when the components involved have different maintainers.
If cyclic module relationships at run time are allowed now then they could not be disallowed in a future release without breaking compatibility; if they are disallowed now, they could still be allowed later on. If they are ever allowed then that would require non-trivial changes to both this specification and its implementations. There are arguments both for and against allowing such relationships, so the safest course of action is to disallow them in this release and wait to see if practical experience with the module system suggests that they should be allowed in a future release.
Multi-module JAR files Define a standard way to package more than one module in a single artifact, while preserving module identities and boundaries.
Strong interest in this feature was expressed only late in the development of this specification. It could easily be designed and implemented in a future release.
Additional module-layer
operations Add further methods to the
ModuleLayer.Controller
API, for use by frameworks and by
other module systems.
Two specific methods have been proposed thus far: An addUses
method,
similar to that already present in the Module
class, and
an addPackage
method, which would add a package to a module that has
already been defined. They carry risks and uncertainties, however, so
they are left for further investigation in a future release. An
addUses
method could make it too easy for service dependences to go
undeclared, which would be confusing, and sophisticated code can likely
work around the lack of this operation via the method-handle API. An
addPackage
method could impose undesirable constraints on the future
evolution of all Java virtual-machine implementations.
The following significant changes were made after the Public-Review Reconsideration Specification:
The draft of the JLS was updated to rely explicitly on the
result of module resolution as specified by the
java.lang.module
package. This reliance occurs both
when compiling ordinary compilation units associated with a module
(§7.3) and when compiling modular compilation units that express
dependences (§7.7.1). In addition, the draft gives a complete
account of the compile-time rules for unnamed modules.
The draft of the JVMS was updated to incorporate all changes to the class-file chapter in support of module declarations, and to clarify when a class file defines a module as opposed to a class or an interface.
The summary of changes to those two documents was simplified to remove text that has been merged into the drafts. The summary is no longer normative.
The specification of the java.util.ServiceLoader
class
was rewritten to align with the draft JLS, clarify the manner in
which service providers are located, and give better guidance on how
to define and use services.
The following changes were made after the second Public Review Specification:
The specification of the
ModuleFinder
interface was revised to say that if a JAR
file is used as an automatic module, and its main manifest includes
an Automatic-Module-Name
attribute, then the value of that
attribute defines the name of the module, per the accepted
proposal.
The draft of the JLS was updated to clarify how a Java language compiler is meant to differentiate between packages with the same name in different modules.
In detail, the possibility of a compiler seeing the same package name
in multiple modules makes it necessary to specify (§4.3.4) that two
reference types with the same fully-qualified name must be
distinguished on the basis of the module that contains each reference
type’s declaration. Correspondingly, the notion of a package’s
“visibility” in potentially multiple modules is augmented by the
notion (§7.4.3) of a package’s “unique visibility” in a given
module. In effect, this considers whether a package is exported from
the given module. It follows that the meaning of package/type names
in code which requires
the given module is specified (§6.5.3,
§6.5.5) with regard to the “uniquely visible” package. Furthermore,
the scope of a top-level package declaration (§6.3) consists of the
compilation units to which the declared package is uniquely visible.
The draft of the JLS was updated
to clarify the tokenization issues that arise for the character
sequence "requires transitive"
(§3.9).
The specification of the module
system’s resolution algorithm, in the java.lang.module
package, was rewritten in order to clarify the definition of
readability and the means by which dependences are resolved at
compile time.
The draft of the JLS was updated to distinguish clearly between access at compile time, access at run time, and reflective access (§7.7), in response to a reader comment.
An addExports
method, similar to that already present in the Module
class, was added to the ModuleLayer.Controller
class, as
agreed.
In the second Public Review Specification the API specification was updated to make two significant changes:
The names of automatic modules, as specified in the
ModuleFinder
interface, can now include trailing digits,
per the accepted proposal.
The Module
, Layer
, and LayerInstantiationException
classes were
moved from the java.lang.reflect
package up into the
java.lang
package and the names of the latter two are
prefixed with Module
, per the accepted proposal.