JEP 11: Incubator Modules

AuthorsChris Hegarty, Alex Buckley
OwnerChris Hegarty
Created2016/11/16 09:17
Updated2017/03/08 11:30
TypeInformational
StatusCandidate
Componentcore-libs
ScopeJDK
Discussionjdk9 dash dev at openjdk dot java dot net
EffortS
DurationS
Priority2
Reviewed byAlan Bateman, Alex Buckley, Brian Goetz, Paul Sandoz
Endorsed byBrian Goetz
Issue8169768

Summary

Incubator modules are a means of putting non-final APIs in the hands of developers while the APIs progress towards either finalization or removal in a future release.

Goals

Enable JDK Release Projects to distribute a limited set of non-final, incubating APIs. This reduces the chance of costly mistakes in the Java SE Platform.

An Incubating API is one for which it is desirable to defer standardization or finalization for one release, in order to gain additional experience with the API. The incubation lifetime of an API is limited: It is expected that the API will either be standardized or otherwise made final in the next release, or else removed.

Non-Goals

Motivation

Many Java SE Platform or supported, JDK-specific APIs would benefit from spending a period of time in a JDK Release Project prior to being standardized in the JCP or otherwise being deemed stable. Being in a JDK Release Project, and thus in downstream binaries such as the Oracle JDK, makes it easier for interested parties outside of the immediate OpenJDK Community to use the new feature. Experience gained and fed back through the usual channels such as blogs, mailing lists, outreach programs, and conferences can then be acted upon before finalizing, or else dropping, the feature in a future Release Project.

Description

An incubator module is a module in a JDK Release Project that exports an incubating feature. An incubating feature is an API of non-trivial size that is under development for eventual inclusion in the Java SE Platform, or the JDK, but is not yet sufficiently proven.

An incubator module identifies itself via the jdk.incubator. prefix in its module name. An incubating feature identifies itself via the jdk.incubator. prefix in its exported package names.

An incubating feature is exported only by an incubator module. If an incubating feature is standardized in the Platform, or otherwise promoted to some stable mode of existence, then its packages will be renamed and then exported from a non-incubator module. Otherwise, if the feature is not standardized or otherwise promoted, then it will no longer be incubating, and its packages and module will be removed.

Because the packages defined by an incubating feature will either be renamed or removed in a future JDK Release Project, and incubating APIs can evolve prior to standardization, early adopters will at the very minimum need to change their import statements, and may need to refactor their uses if the API changes more substantially.

Process and Evolution

An incubating feature will use the JEP process as is, with the following guidelines:

  1. The JEP that defines the feature intended for incubation should make that clear, and the result of completing the JEP will be an incubator module that exports that feature's API.

  2. An incubating feature, along with any evolutionary API changes, that is later promoted to the Platform, or some other stable mode of existence, should have a new JEP to propose and document that change. At the time of the new JEP, there is no need to deliver the promoted API in its own module; it may be integrated into an existing standard module or a non-incubator JDK-specific module.

  3. If an incubating feature is later removed then no new JEP is necessary. The incubator module that contains the incubating feature may be silently removed. It is recommended that the original JEP be updated to record the fate of the feature.

One incubator module should contain one incubating feature. Mapping one incubating feature to one incubator module will help prevent the emergence of a "miscellaneous" incubator module that acts as a dumping ground, as has been seen in the past in some parts of the legacy sun.* namespace. There is clear ownership of incubating features and their impending, or not, future.

An incubating feature need not be retained forever in the JDK Release Project in which it was introduced, nor in every release of downstream binaries derived from that Release Project. For example, it may evolve, or even be removed, between different update releases of a downstream release. Beyond this explicit statement of when evolution is permitted, this proposal deliberately provides no further guidance. Such decisions are best left to the individual feature owner.

An incubator module, and its API, could be considered to be terminally deprecated, but the @Deprecated annotation and the @deprecated JavaDoc tag should not be used in incubator modules. Incubation and deprecation are related but different concepts.

Relationship to other modules

Incubator modules can only export incubating features. Consequently, incubator modules cannot export APIs in the java. or javax. namespaces governed by the JCP, and so are distinct from standard modules such as java.base.

Incubator modules do not export supported JDK APIs, and so are distinct from JDK-specific modules such as jdk.compiler that do export such APIs. Incubator modules do not export critical internal APIs, and so have no relationship to the jdk.unsupported module.

Standard and non-incubator JDK-specific modules must not specify requires transitive dependences upon incubator modules, or otherwise expose types exported from incubator modules in their own exported APIs. In exceptional cases, it may be acceptable for standard and non-incubator JDK-specific modules to specify requires dependences upon incubator modules.

Incubator modules can specify requires or requires transitive dependences upon other incubator modules.

Incubator modules are part of the JDK run-time image produced by the standard JDK build. However, incubator modules are not resolved by default for applications on the class path. Applications on the class path must use the --add-modules command-line option to request that an incubator module be resolved. Applications developed as modules can specify requires or requires transitive dependences upon an incubator module directly.

During the JDK build incubator modules must be packaged into jmod files with the --do-not-resolve-by-default option of the jmod tool, so that they are not in the default set of root modules for the unnamed module. This makes them, in effect, "opt-in". The --warn-if-resolved=incubator option must be also passed to the jmod tool, so that a warning is issued at compile time, link time, and run time if the incubator module is resolved. This warning can be suppressed at compile time, but not at other times.

Incubator modules are granted no default security permissions. Incubator modules can be operating-system specific.

Integration points

Many features, and their APIs, are tightly integrated with the Java SE Platform. An API defined by an incubating feature will reside within the jdk.incubator. namespace, and therefore will not be part of the Platform. Integration points with existing Platform types may be challenging, and certain compromises may need to be made while the API is in incubation. For example, for the Streams API it may have been necessary for a notional jdk.incubator.stream.Streams class to provide static factory methods such as fromList, fromSet, etc., to enable integration with the existing Collections API. While this is a compromise, integration points with the existing Platform typically represent a relatively small surface of a new API.

In some cases an incubating feature may be tightly integrated with the Java run-time system and the JVM. In such cases low-level operations can be exposed through qualified exports from the appropriate module(s) in the JDK build to the incubator module containing the feature. An incubator module that has at least one qualified export from a module in the JDK build must be tightly coupled, i.e., its hash must be recorded in the exporting module, and the incubator module is therefore not upgradeable. An incubator module that does not have any qualified exports from a module in the JDK need not be tightly coupled, and may therefore be upgradeable. If underlying incubation support is required in the JVM then it may be necessary to provide a command-line argument, e.g., -XX:+UnlockExperimentalVMOptions, or else arrange to enable such support automatically in the presence of the incubator module.

Documentation

An incubating feature will have its JavaDoc built as part of the JDK docs build, in the same way as other JDK-specific APIs. An additional directory structure, jdk/incubator/ will be added so as to group the documentation of incubating features on a per-module basis. All JavaDoc built for incubating features will have an explicit, obvious, and consistent warnings about the incubating state of the feature, and will caution that the feature will eventually be removed.

Alternatives

Many new features are tightly integrated with the Java run-time system and the JVM. Distributing them independently of the JDK would thus be difficult, if not impossible, since they need to be tightly tied to a particular build of a particular release. Distributing them with the JDK ensures that all the necessary pieces are tightly coupled.

Downstream early-access binaries of a JDK Release Project still under development, such as the Oracle JDK 9 Early Access Releases, are expected to continue. Feedback on early-access (EA) releases has been, and continues to be, very valuable, but historically the number of EA downloads has been much smaller than that of the final Generally Available (GA) releases. Incubating features are aimed at a wider range of developers, some of which may never test EA releases, and may desire the higher level of stability and quality provided by GA releases.

Testing

The code comprising an incubating feature should be tested as any other within the JDK. Specific feature testing requirements should be outlined by the JEP delivering the incubating feature.

Risks and Assumptions

The obvious risk with an incubating feature is that someone's code will come to depend upon it and then be "broken" when run on a later release, in which the incubator feature's module has been removed. This risk is mitigated by ensuring that incubating features are opt-in, i.e., by not resolving incubator modules by default, and by issuing warnings, in all phases, when incubator modules are resolved.