Proposal: #CompileTimeDependences: `requires static`
Mark Reinhold
mark.reinhold at oracle.com
Tue Jun 28 21:17:15 UTC 2016
Issue summary
-------------
#CompileTimeDependences --- Provide a means to specify a module
dependence that is mandatory at compile time but optional at run time,
for use with libraries that are not strictly necessary but can be
leveraged if present at run time. (Detail: If a dependence is
"optional at run time" then does the module system try to satisfy it
during resolution but fail silently if it cannot, or does it ignore it
during resolution but add the corresponding read edge to that module if
it was resolved for some other reason?) [1]
Use cases for this feature include annotations that need not be present
at run time [2] and "auto-configuring" libraries and frameworks such as
Joda Beans [3] and Spring [4].
Proposal
--------
Extend the language of module declarations to allow the `static` modifier
to be used on a `requires` directive, with the following meanings:
- At compile time, `requires static M` expresses a mandatory
dependence. It is an error if a suitable module cannot be found
amongst the observable modules and resolved.
- In phases after compile time, `requires static M` expresses an
optional dependence. The module system will not search the
observable modules for a suitable module during resolution, but
if the resulting module graph contains a suitable module then it
will add the appropriate readability edge prior to doing the usual
post-resolution sanity checks. (The parenthetical question in the
issue summary is, in other words, answered in the negative.)
Thus a hypothetical module declaration of the form
module joda.beans {
requires static joda.collect;
...
}
would ensure that the `joda.collect` module is available at compile time,
so that code in the `joda.beans` module that refers to `joda.collect` can
be compiled without any fuss. It would not, however, guarantee that
`joda.collect` is available at link time or run time. A user who wants
to use `joda.beans` together with `joda.collect` in those later phases
must ensure that `joda.collect` is added to the module graph by, e.g.,
declaring a dependence upon it in some other module, or by using the
`-addmods` option or its equivalent.
The code in `joda.beans` that refers to types in `joda.collect` must, of
course, be written defensively so that it fails gracefully at run time
when the `joda.collect` module is not present.
It is possible to combine the `public` and `static` modifiers on a
`requires` directive:
module joda.beans {
requires static joda.collect;
requires public static freemarker;
...
}
This is useful in this particular case since `joda.beans` defines two
exported public classes that extend classes defined in the `freemarker`
module, and so those classes are logically part of the `joda.beans` API.
In general, however, this idiom leads to fragile APIs and is therefore
not advised except when dealing with legacy code.
Notes
-----
- In phases after compile time, why doesn't the module system search
the observable modules in an attempt to satisfy an optional
dependence?
This would not be difficult to arrange but it could lead to surprising
behavior in which optional dependences silently cause many additional
modules to be resolved. Given the use cases we have it does not seem
unreasonable to expect an end user to indicate explicitly, either in
source code or out-of-band (e.g., with a command-line option such as
`-addmods`), that an otherwise-optional module is actually needed.
[1] http://openjdk.java.net/projects/jigsaw/spec/issues/#CompileTimeDependences
[2] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-October/004915.html
[3] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-December/005462.html
[4] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-December/005814.html
More information about the jpms-spec-observers
mailing list