JEP 11: Incubator Modules
|Authors||Chris Hegarty, Alex Buckley|
|Discussion||jdk9 dash dev at openjdk dot java dot net|
|Reviewed by||Alan Bateman, Alex Buckley, Brian Goetz, Paul Sandoz|
|Endorsed by||Brian Goetz|
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.
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.
It is not a goal to define a general-purpose mechanism to distribute arbitrary non-JDK modules.
It is not a goal to define the complete lifecycle of a module or API.
It is not a goal that every feature being developed for the JDK be, at some point in its lifecycle, incubated (though that may be desirable).
It is not a goal to define a mechanism for incubating language or VM features, but any such a future mechanism should use incubator modules for their relevant APIs.
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.
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:
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.
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.
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
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
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
namespaces governed by the JCP, and so are distinct from standard
modules such as
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
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 can specify
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
requires transitive dependences upon an incubator
During the JDK build incubator modules must be packaged into
--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
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.
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
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.
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
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.
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.
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.