Proposal: #AddExportsInManifest

Mark Reinhold mark.reinhold at oracle.com
Mon Sep 12 15:09:01 UTC 2016


Issue summary
-------------

  #AddExportsInManifest -- Using a command-line option such as
  `--add-exports` to make JDK-internal APIs available to existing code is
  difficult, if not impossible, for applications that are delivered as
  executable JAR files.  To ease migration, consider allowing such a JAR
  file to include the equivalent of such options in its `MANIFEST.MF`
  file. [1]

Proposal
--------

Define two new JAR-file manifest attributes [2], `Add-Exports` and
`Add-Exports-Private`.  Each attribute can occur at most once, in the
main section of a `MANIFEST.MF` file.  The parameter of each attribute is
a space-separated list of slash-separated module-name/package-name pairs.
At run time the presence of a pair `m/p` in the value of each attribute
is interpreted as follows:

  - If `m/p` is listed in the value of the `Add-Exports` attribute then
    package `p` of module `m` is exported to all unnamed modules, as if
    by invoking the `Module::addExports` method.  This makes all of
    package `p`'s public elements immediately accessible to code in
    unnamed modules.

  - If `m/p` is listed in the value of the `Add-Exports-Private`
    attribute then package `p` of module `m` is exported to all unnamed
    modules and its non-public elements are made available for deep
    reflection, as if by invoking the `Module::addExportsPrivate` method
    [3].  This makes all of package `p`'s public elements immediately
    accessible to code in the unnamed module, and all of its non-public
    elements accessible to code in unnamed modules via the
    `setAccessible` method of the core reflection API.

In contrast to language-level module declarations some sloppiness is
allowed in the values of these attributes, as is traditional in JAR-file
manifests.  A particular module-name/package-name pair can be listed more
than once in either of these attributes.  It can also be listed in both
attributes, in which case the package will be exported privately.  A
module or package specified in such a pair need not actually exist in
the run-time module graph.

These attributes are interpreted only in the main executable JAR file
of an application, i.e., in the JAR file specified to the `-jar`
command-line option of typical Java run-time launchers.  They are
ignored in all other JAR files.

As an example, the Spring Boot framework [4] uses `setAccessible` to
access a protected `defineClass` method of `java.lang.ClassLoader` and
a private constructor of `java.lang.invoke.MethodHandles.Lookup`.  An
application that uses Spring Boot can be made to work by adding the
line

    Add-Exports-Private: java.base/java.lang java.base/java.lang.invoke

to the `MANIFEST.MF` file of its executable JAR file.


[1] http://openjdk.java.net/projects/jigsaw/spec/issues/#AddExportsInManifest
[2] http://download.java.net/java/jdk9/docs/technotes/guides/jar/jar.html#JAR_Manifest
[3] See the nearby proposal for #ReflectiveAccessToNonExportedTypes
[4] http://projects.spring.io/spring-boot/


More information about the jpms-spec-experts mailing list