JEP 260: Encapsulate Most Internal APIs
Author | Mark Reinhold |
Owner | Chris Hegarty |
Type | Feature |
Scope | JDK |
Status | Closed / Delivered |
Release | 9 |
Discussion | jigsaw dash dev at openjdk dot java dot net |
Effort | M |
Duration | L |
Blocks | JEP 261: Module System |
Relates to | JEP 396: Strongly Encapsulate JDK Internals by Default |
JEP 403: Strongly Encapsulate JDK Internals | |
Reviewed by | Alan Bateman, Alex Buckley, Brian Goetz, John Rose, Paul Sandoz |
Endorsed by | Brian Goetz |
Created | 2015/08/03 18:29 |
Updated | 2024/04/28 18:11 |
Issue | 8132928 |
Summary
Encapsulate most of the JDK's internal APIs by default so that they are inaccessible at compile time, and prepare for a future release in which they will be inaccessible at run time. Ensure that critical, widely-used internal APIs are not encapsulated, so that they remain accessible until supported replacements exist for all or most of their functionality.
Non-Goals
This JEP does not define replacements for any internal APIs; that work is or will be covered by separate JEPs and, where appropriate, JSRs.
This JEP does not commit to preserve the compatibility of any internal APIs across releases; they continue to remain unstable and subject to change without notice.
Motivation
Some popular libraries make use of non-standard, unstable, and unsupported APIs that are internal implementation details of the JDK and were never intended for external use. In the modular JDK (JEP 200), limiting access to these APIs by leveraging the module system (JEP 261) improves the integrity and security of the platform since many of these internal APIs define privileged, security-sensitive operations. In the long run this change will reduce the costs borne by the maintainers of the JDK itself and by the maintainers of libraries and applications that, knowingly or not, make use of these internal APIs.
Description
Based upon analyses of various large collections of code, including Maven
Central, and also feedback received since the release of JDK 8 and its
dependency analysis tool (jdeps
), we divide the JDK's internal
APIs into two broad categories:
-
Non-critical internal APIs which do not appear to be used by code outside of the JDK or are used by outside code merely for convenience, i.e., for functionality that is available in supported APIs or can easily be provided by libraries (e.g.,
sun.misc.BASE64Decoder
); and -
Critical internal APIs which provide critical functionality that would be difficult, if not impossible, to implement outside of the JDK itself (e.g.,
sun.misc.Unsafe
).
Critical internal APIs are encapsulated in JDK 9, or not, according
to whether supported replacements exist in JDK 8. A supported
replacement is one that was either part of the Java SE 8 standard,
i.e., in a java.*
or javax.*
package, or else JDK-specific and
annotated with @jdk.Exported
, typically in a com.sun.*
or jdk.*
package. In detail:
-
Critical internal APIs for which supported replacements exist in JDK 8 are encapsulated in JDK 9.
-
Critical internal APIs for which supported replacements did not exist in JDK 8 are not encapsulated in JDK 9. A detailed list is provided below.
-
Critical internal APIs for which supported replacements exist in JDK 9 are deprecated and will be either encapsulated or removed in a future release.
All non-critical internal APIs are encapsulated in JDK 9.
Internal APIs that are encapsulated in JDK 9 are inaccessible at
compile time. They can be made accessible at compile time via the
--add-exports
command-line option. At run time they
remain accessible if they were in JDK 8 but in a future release they
will become inaccessible, at which point the --add-exports
or
--add-opens
options can be used to make them accessible at run time as
well. The --illegal-access
option
controls the run-time accessibility of these APIs and
can be used to emulate the future run-time inaccessibility of internal
APIs.
Critical internal APIs not encapsulated in JDK 9
The critical internal APIs that are not encapsulated in JDK 9, because supported replacements did not exist in JDK 8, are listed here.
-
sun.misc.{Signal,SignalHandler}
-
sun.misc.Unsafe
(The functionality of many of the methods in this class is available via variable handles (JEP 193).) -
sun.reflect.Reflection::getCallerClass(int)
(The functionality of this method is available in the stack-walking API defined by JEP 259.) -
sun.reflect.ReflectionFactory
-
com.sun.nio.file.{ExtendedCopyOption,ExtendedOpenOption, ExtendedWatchEventModifier,SensitivityWatchEventModifier}
These APIs are defined in, and exported by, the JDK-specific
jdk.unsupported
module. This module is present in full JRE and JDK
images. These APIs are thus accessible by default to code on the class
path, and accessible to code in modules if those modules declare
dependences upon the jdk.unsupported
module.
Critical internal APIs for which replacements are introduced in JDK 9 are deprecated in JDK 9 and will be either encapsulated or removed in a future release.
A consequence of jdk.unsupported
exporting and opening the sun.misc
and sun.reflect
packages is that all non-critical internal APIs in
those packages were either moved to some other package or removed, as
appropriate. Standard and JDK modules that are not upgradeable should
not depend upon the jdk.unsupported
module, but instead use proper
internal APIs.
Maintainers of libraries that use critical internal APIs for which replacements exist in JDK 9 may wish to use Multi-Release JAR Files (JEP 238) in order to ship single artifacts that use the old APIs on releases prior to JDK 9 and the replacement APIs on later releases.
Risks and Assumptions
If some widely-used critical internal API was not identified as critical, and that API was moved or removed, then applications that depend upon it will fail.
If some widely-used critical internal API was not identified as critical but still exists then applications that depend upon it may cause a warning to be issued in this release and will fail in a future release.
The short-term workaround for both such situations is for the end user to
expose the API via the above-mentioned command-line option; in the longer
term, in a later release the API could be moved to the jdk.unsupported
module and exported for external use.
The non-critical internal APIs previously present in the sun.misc
and
sun.reflect
packages have been either moved or removed. Existing code
that depends upon them may not work correctly.
Dependences
JEP 200 (The Modular JDK) defines the modular structure of the JDK, and JEP 261 (Module System) implements the module system.