Summary
Strongly encapsulate all internal elements of the JDK by default, except
for critical internal APIs such as sun.misc.Unsafe
. Allow end
users to choose the relaxed strong encapsulation that has been the
default since JDK 9.
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.
We released JDK 9 in September 2017. Most of the commonly-used
internal elements of the JDK now have standard replacements.
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
.
Solution
Change the default mode of the
--illegal-access
option frompermit
todeny
. With this change, packages that existed in JDK 8 and do not contain critical internal APIs will no longer be open by default; a complete list is available here. Thesun.misc
package will still be exported by thejdk.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 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.
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 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>
- blocks
-
JDK-8255363 JEP 396: Strongly Encapsulate JDK Internals by Default
-
- Closed
-
- csr of
-
JDK-8256299 Implement JEP 396: Strongly Encapsulate JDK Internals by Default
-
- Resolved
-