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

      Make most of the JDK's internal APIs inaccessible by default but leave a few critical, widely-used internal APIs accessible, until supported replacements exist for all or most of their functionality.

      Non-Goals

      This JEP will not itself propose replacements for any internal APIs; that work 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. Limiting access to these APIs by leveraging the forthcoming module system (JEP 200) will improve 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 can divide the JDK's internal APIs into two broad categories:

      • Those 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

      • Those which provide critical functionality that would be difficult, if not impossible, to implement outside of the JDK itself (e.g., sun.misc.Unsafe).

      In JDK 9 we propose to:

      • Encapsulate all non-critical internal APIs by default: The modules that define them will not export their packages for outside use. (Access to such APIs will be available, as a last resort, via a command-line flag at both compile time and run time, unless those APIs are revised or removed for other reasons.)

      • Encapsulate critical internal APIs for which supported replacements exist in JDK 8, in the same manner and with the same last-resort workaround. (A supported replacement is one that is 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).)

      • Not encapsulate critical internal APIs for which supported replacements do not exist in JDK 8 and, further, deprecate those which have supported replacements in JDK 9 with the intent to encapsulate them, or possibly even remove them, in JDK 10.

      The critical internal APIs proposed to remain accessible in JDK 9 are:

      • sun.misc.{Signal,SignalHandler}

      • sun.misc.Unsafe (The functionality of many of the methods in this class is now available via variable handles (JEP 193).)

      • sun.reflect.Reflection::getCallerClass(int) (The functionality of this method may be provided in a standard form via JEP 259.)

      • sun.reflect.ReflectionFactory.newConstructorForSerialization

      Suggested additions to this list, justified by real-world use cases and estimates of developer and end-user impact, are welcome.

      The above critical internal APIs will be placed in, and their packages exported and opened from, a JDK-specific module named jdk.unsupported. This module will be present in full JRE and JDK images. These APIs will therefore be 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.

      As noted above, replacements for some of these internal APIs already exist, in whole or in part, in JDK 9. Developers are strongly encouraged to test these replacements in the JDK 9 early-access builds and send feedback if the replacements are not sufficient or could be improved.

      Critical internal APIs for which replacements are introduced in JDK 9 will be deprecated in JDK 9 and either encapsulated or removed in JDK 10.

      The consequence of jdk.unsupported exporting and opening sun.misc and sun.reflect is that:

      • non-critical internal APIs in the sun.misc and sun.reflect packages will be moved, or removed as appropriate, since they should not be accessible

      • standard and JDK modules cannot depend on jdk.unsupported

      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 is not identified by the time that JDK 9 is released then applications that depend upon it will fail. The short-term workaround for such a situation would be for the end user to expose the API via the above-mentioned command-line flag; in the longer term, in a JDK 9 update release the API could be moved to the jdk.unsupported module and exported for external use.

      Since the jdk.unsupported module will export and open sun.misc and sun.reflect, all non-critical internal APIs in these packages will be moved, or removed, as appropriate. If removed they will no longer be visible or accessible. If moved they will be accessible, through the use of a command-line flag, but their fully qualified name will be changed, i.e. they will be in a package of another name.

      Beyond the proposed critical APIs for sun.reflect, said package contains the machinery that implements the java.lang(.reflect) subsystem. That machinery will be moved to an internal, non-exported, package in the base module. Consequently, the stack trace of reflective calls will appear somewhat different. That is, stack frames that represent the reflective implementation will see their class name ( StackTraceElement.getClassName() ) change from sun.reflect.XXX to jdk.internal.reflect.XXX. Any code analysing, or filtering, based on the stack trace element's class name should be updated appropriately, to handle this. See 8137058 for further details.

        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:
                Integration Due: