JDK-8256300 : CSR for JEP 396: Strongly Encapsulate JDK Internals by Default
  • Type: CSR
  • Component: core-libs
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 16
  • Submitted: 2020-11-12
  • Updated: 2020-11-18
  • Resolved: 2020-11-18
Related Reports
Blocks :  
CSR :  
Description
Summary
-------

Strongly encapsulate all internal elements of the JDK by default, except
for [critical internal APIs][crit] such as `sun.misc.Unsafe`.  Allow end
users to choose the relaxed strong encapsulation that has been the
default since JDK 9.

[crit]: https://openjdk.java.net/jeps/260#Description

Problem
-------

Over the years the developers of various libraries, frameworks, tools,
and applications have used internal elements of the JDK in ways that
compromise both security and maintainability.

In Java 9, we improved both the security and the maintainability of
the JDK by strongly encapsulating all new internal elements, thereby
limiting access to them.  As an aid to migration, however, we
deliberately chose not to strongly encapsulate, at run time, the content
of packages that existed in JDK 8.  Library and application code on
the class path could thus continue to use reflection to access the
non-`public` elements of `java.*` packages, and all elements of `sun.*`
and other internal packages, for packages that existed in JDK 8.
This arrangement is called [_relaxed strong encapsulation_][relax].

We released JDK 9 in September 2017.  Most of the commonly-used
internal elements of the JDK now have [standard replacements][replace].
Developers have had over three years in which to migrate away from
internal elements of the JDK to standard APIs such as
`java.lang.invoke.MethodHandles.Lookup::defineClass`, `java.util.Base64`,
and `java.lang.ref.Cleaner`.  Many library, framework, and tool
maintainers have completed that migration and released updated versions
of their components.  We are now ready to take the next step toward the
strong encapsulation of all internal elements of the JDK ��� except for
critical internal APIs such as `sun.misc.Unsafe`.

[relax]: https://openjdk.java.net/jeps/261#Relaxed-strong-encapsulation
[replace]: https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool#JavaDependencyAnalysisTool-ReplaceusesoftheJDK'sinternalAPIs

Solution
--------

  - Change the default mode of the `--illegal-access` option from
    `permit` to `deny`.  With this change, packages that existed in
    JDK 8 and do not contain [critical internal APIs][crit] will no
    longer be open by default; a complete list is available
    [here][jdk8-pkgs].  The `sun.misc` package will still be exported by
    the `jdk.unsupported` module, and will still be accessible via
    reflection.

  - Deprecate the `--illegal-access` option for removal in a future
    release, and arrange for a deprecation warning to be issued when it
    is used.

  - Revise the related text in the [Java Platform Specification][se9-relax]
    to disallow the opening of any package by default in any Java
    Platform Implementation, unless that package is explicitly declared
    to be `open` in the declaration of its containing module.

  - No change to `javac` is needed, since internal elements of the JDK
    have been strongly encapsulated by default since JDK 9.

A detailed discussion of this change and its likely impact can be found
in [JEP 396](https://openjdk.java.net/jeps/396).

[se9-relax]: https://cr.openjdk.java.net/~iris/se/9/java-se-9-fr-spec-01/#Relaxing-strong-encapsulation
[jdk8-pkgs]: https://bugs.openjdk.java.net/secure/attachment/91418/jdk8-packages-encapsulated-by-default.txt


Specification
-------------

### Man page for the `java` launcher

    @@ -814,38 +814,36 @@ the Java HotSpot Virtual Machine.

     `--illegal-access=`*parameter*
     :   When present at run time, `--illegal-access=` takes a keyword *parameter*
         to specify a mode of operation:

    -    > **Note:** This option will be removed in a future release.
    +    > **Note:** This option is deprecated and will be removed in a future release.

         -   `permit`: This mode opens each package in each module in the run-time
             image to code in all unnamed modules ( such as code on the class path),
             if that package existed in JDK 8. This enables both static access, (for
             example, by compiled bytecode, and deep reflective access) through the
             platform's various reflection APIs. The first reflective-access
             operation to any such package causes a warning to be issued. However,
             no warnings are issued after the first occurrence. This single warning
    -        describes how to enable further warnings. This mode is the default for
    -        the current JDK but will change in a future release.
    +        describes how to enable further warnings.

         -   `warn`: This mode is identical to `permit` except that a warning
             message is issued for each illegal reflective-access operation.

         -   `debug`: This mode is identical to `warn` except that both a warning
             message and a stack trace are issued for each illegal reflective-access
             operation.

         -   `deny`: This mode disables all illegal-access operations except for
             those enabled by other command-line options, such as `--add-opens`.
    -        This mode will become the default in a future release.
    +        This mode is the default.

    -    The default mode, `--illegal-access=permit`, is intended to make you aware
    -    of code on the class path that reflectively accesses any JDK-internal APIs
    -    at least once. To learn about all such accesses, you can use the `warn` or
    -    the `debug` modes. For each library or framework on the class path that
    -    requires illegal access, you have two options:
    +    If your application does not work with the default mode of
    +    `--illegal-access=deny` then you can learn more about what is going
    +    on with the `warn` and `debug` modes. For each library or framework
    +    on the class path that requires illegal access, you have two options:

         -   If the component's maintainers have already released a fixed version
             that no longer uses JDK-internal APIs then you can consider upgrading
             to that version.

### ���Relaxing strong encapsulation��� subsection of the Java SE Platform Specification

Rather than incorporate the text of this section from the
[Java SE 9 Platform Specification][se9-relax] by reference, the new
Platform Specification will instead include this text:

    <p><title>Relaxing strong encapsulation</title> As an aid to migration, an
    Implementation may provide a means to invoke its run-time system with one
    or more packages of one or more of its modules open to code in all unnamed
    modules, &ie;, to code on the class path.  If the run-time system is
    invoked in this way, and if by doing so some invocations of the reflection
    APIs succeed where otherwise they would have failed, then the first such
    invocation must cause a warning to be issued on the standard error stream.
    Later such invocations may also cause warnings to be issued. </p>

    <p> (The Reference Implementation provides this capability via the
    command-line option <code>--illegal-access=permit</code>.) </p>

    <p> An Implementation must not, by default, relax the strong encapsulation
    of any of its modules.  That is, its run-time system must not customarily
    behave as if various packages in the Implementation's modules are open when
    they are not open according to their module declarations.  A package, or an
    entire module, is open to code in all unnamed modules if and only if: </p>

    <ul>

      <li> It is explicitly declared to be open, without qualification, in a
      module declaration, or </li>

      <li> The run-time system is explicitly invoked to open it to code in all
      unnamed modules, <a href="#Overriding-module-declarations">as provided
      for below</a>. </li>

    </ul>

    <p> A future revision of this Specification is expected to disallow relaxed
    strong encapsulation entirely. </p>

[se9-relax]: https://cr.openjdk.java.net/~iris/se/9/java-se-9-fr-spec-01/#Relaxing-strong-encapsulation

Comments
Thanks for the additional information; moving to Approved.
18-11-2020

There is no behavior change to javac, which has forbidden the use of internal APIs by default since JDK 9. I���ve added a statement to that effect in the CSR text above, and will add a similar statement to the JEP.
17-11-2020

Moving to Provisional. Is it correct that there is no behavior change in javac, only in java command at runtime?
17-11-2020