Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8132928

JEP 260: Encapsulate Most Internal APIs

    Details

    • Author:
      Mark Reinhold
    • JEP Type:
      Feature
    • Exposure:
      Open
    • Scope:
      JDK
    • Discussion:
      jigsaw dash dev at openjdk dot java dot net
    • Effort:
      M
    • Duration:
      L
    • Alert Status:
       Green
    • JEP Number:
      260

      Description

      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.

        Issue Links

          Activity

          Hide
          chegar Chris Hegarty added a comment - - edited
          Removing the open issue referring to sun.misc.Cleaner.

          sun.misc.Cleaner was previously listed as a critical internal API, but on further investigation has been removed, for the following reasons: 1) its primary use in the JDK is within NIO direct buffers to release native memory. The base module cannot have a dependency on jdk.unsupported so will need to be updated to use an alternative cleaner, 2) the usage of Cleaner outside the JDK, as determined by corpus analysis, has largely been observed to hack into private fields of the internal NIO direct buffer classes to explicitly release native memory. As stated in 1), the type of the cleaner used by NIO direct buffers will have to change. Given this, and the fact that JDK 9 has a new general purposed cleaner API, java.lang.ref.Cleaner, the value of keep sun.misc.Cleaner is questionable. See JDK-8148117 for further details.
          Show
          chegar Chris Hegarty added a comment - - edited Removing the open issue referring to sun.misc.Cleaner. sun.misc.Cleaner was previously listed as a critical internal API, but on further investigation has been removed, for the following reasons: 1) its primary use in the JDK is within NIO direct buffers to release native memory. The base module cannot have a dependency on jdk.unsupported so will need to be updated to use an alternative cleaner, 2) the usage of Cleaner outside the JDK, as determined by corpus analysis, has largely been observed to hack into private fields of the internal NIO direct buffer classes to explicitly release native memory. As stated in 1), the type of the cleaner used by NIO direct buffers will have to change. Given this, and the fact that JDK 9 has a new general purposed cleaner API, java.lang.ref.Cleaner, the value of keep sun.misc.Cleaner is questionable. See JDK-8148117 for further details.

            People

            • Assignee:
              chegar Chris Hegarty
              Reporter:
              mr Mark Reinhold
              Owner:
              Chris Hegarty
              Reviewed By:
              Alan Bateman, Alex Buckley, Brian Goetz, John Rose, Paul Sandoz
              Endorsed By:
              Brian Goetz
            • Votes:
              1 Vote for this issue
              Watchers:
              13 Start watching this issue

              Dates

              • Due:
                Created:
                Updated:
                Resolved:
                Integration Due: