Proposal: #ModuleAnnotations and #ModuleDeprecation

Mark Reinhold mark.reinhold at oracle.com
Tue Jun 28 21:19:15 UTC 2016


Issue summaries
---------------

  #ModuleAnnotations --- Should it be possible to annotate module
  declarations?  As previously discussed this is technically feasible
  but it would add significant complexity. [1]

  #ModuleDeprecation -- If module declarations cannot be annotated,
  should there be some other way to deprecate modules? [2]

Proposal
--------

Allow arbitrary annotations to be placed on module declarations, and
revise the `java.lang.Deprecated` annotation so that it can be applied
to modules.

  - Add a new value, `MODULE`, to `java.lang.annotation.ElementType`,
    to denote the top level of a module declaration.

  - Extend `javax.lang.model` and `java.lang.reflect` to provide access
    to module annotations.  Repeating annotations are supported, subject
    to the usual rules for repeatable annotation types.  (This proposal
    will not add similar support to `java.lang.module.ModuleDescriptor`;
    that would add yet more complexity, and we haven't seen a use case
    for it.)

  - Annotations on modules will never affect the operation of the module
    system itself.

  - Revise `java.lang.Deprecated` and `java.lang.SuppressWarnings` to
    allow `ElementType.MODULE` as a target.  For now, no other existing
    Java SE annotations will apply to modules.

Also, allow `import` declarations [3] to be used in module compilation
units.

  - Any `import` declarations must appear before the `module` declaration.

  - As a consequence of supporting `import` declarations, simple type
    names can now be used in the `uses` and `provides` directives of a
    module declaration.  Type annotations on these type names are not
    supported.

Rationale
---------

When we first discussed this topic I wrote [4]:

> We haven't seen a compelling use case (so far) for annotations on module
> declarations, or on clauses in module declarations, and they aren't a
> documented requirement, so for simplicity we left them out of the initial
> design and the prototype.

The compelling use case is, of course, deprecation, as Rémi pointed out
[5].  In Java SE 9, in particular, we very much want to be able to write
something like this:

    @Deprecated(since = "9", forRemoval = true)
    module java.corba {
        ...
    }

The most natural way to do this is to allow module declarations to be
annotated in the same way as other top-level declarations (i.e., packages
and classes).  If we don't allow the `@Deprecated` annotation to be used
on modules then we'd have to invent some other way to deprecate modules
(another new keyword?), and that would just be confusing.

Like most language features, annotations have sometimes been over-used
and even abused [6].  Allowing modules to be annotated opens up a whole
new avenue for unfortunate design decisions that lead to unreadable code.
We could try to limit the damage by allowing just a few annotations on
module declarations (e.g., only those in the `java.lang` package), or by
not supporting `import` declarations so that the use of non-platform
annotations is discouragingly verbose.  Such an approach would lead to
unpleasant asymmetries in the language, however, so instead we propose to
support arbitrary annotations on module declarations in the obvious way.

I think the guidance I wrote earlier [4] still holds.  Annotations are
useful for extra-linguistic statements, such as deprecation, that make
sense in source code and can usefully be carried through the tool chain
into the resulting class file.  I still don't think they're appropriate
for information that is more appropriately the domain of build systems,
e.g., version strings.

Notes
-----

  - Should it be possible to annotate the individual directives in a
    module declaration?  This would allow you to deprecate individual
    exports and requires-public directives, which could be useful in the
    process of evolving an API: If you plan to remove a package, or
    remove a public dependence upon some other module, then you could
    deprecate the corresponding `exports` or `requires public` directive
    (presumably with `forRemoval = true`) to warn your users that the
    API is going to change.

There are no cases in the JDK itself where we need this ability, at least
not desperately.  Designing and implementing this would be a non-trivial
exercise, and it is a separable feature that could be added later on if
justified by experience.


[1] http://openjdk.java.net/projects/jigsaw/spec/issues/#ModuleAnnotations
[2] http://openjdk.java.net/projects/jigsaw/spec/issues/#ModuleDeprecation
[3] http://docs.oracle.com/javase/specs/jls/se8/html/jls-7.html#jls-7.5
[4] http://mail.openjdk.java.net/pipermail/jpms-spec-experts/2015-October/000153.html
[5] http://mail.openjdk.java.net/pipermail/jpms-spec-experts/2016-March/000263.html
[6] http://annotatiomania.com/


More information about the jpms-spec-observers mailing list