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

JEP 247: Compile for Older Platform Versions

    Details

    • Author:
      Jan Lahoda
    • JEP Type:
      Feature
    • Exposure:
      Open
    • Subcomponent:
    • Scope:
      JDK
    • Discussion:
      compiler dash dev at openjdk dot java dot net
    • Effort:
      M
    • Duration:
      L
    • Alert Status:
       Green
    • JEP Number:
      247

      Description

      Summary

      Enhance javac so that it can compile Java programs to run on selected older versions of the platform.

      Motivation

      javac provides two command line options, -source and -target, which can be used to select the version of the Java language accepted by the compiler and the version of the class files it produces, respectively. By default, however, javac compiles against the most-recent version of the platform APIs. The compiled program can therefore accidentally use APIs only available in the current version of the platform. Such programs cannot run on older versions of the platform, regardless of the values passed to the -source and -target options. This is a long-term usability pain point, since users expect that by using these options they'll get class files that can run on the the platform version specified by -target.

      Description

      A new command-line option, --release, is defined, which automatically configures the compiler to produce class files that will link against an implementation of the given platform version. --release N is roughly equivalent to:

      • for N < 9: -source N -target N -bootclasspath <documented-APIs-from-N>,
      • for N >= 9: -source N -target N --system <documented-APIs-from-N>.

      For N < 9, the documented APIs consist of the public APIs that were on javac's default bootclasspath for JDK N.

      For N >= 9, the documented APIs consist of (i) the APIs exported from those modules in the JDK image which are part of the documentation of JDK N; and (ii) the API exported from the jdk.unsupported module (documented in JEP 260). That is, the documented APIs are primarily the APIs exported by the intersection of the modules in the JDK image and the modules documented for JDK N. No other modules in the JDK image are observable. If --limit-modules is used, then it can only further limit the observable modules, not observe additional modules. Access to internals of the modules in the JDK image is not allowed.

      The --release N option is incompatible with other options that affect the set of platform or system classes. This includes:

      • for N < 9: -bootclasspath, -Xbootclasspath, -Xbootclasspath/a:, -Xbootclasspath/p:, -endorseddirs, -Djava.endorsed.dirs, -extdirs, -Djava.ext.dirs options that set platform classes.
      • for N >= 9: the --system and --upgrade-module-path options that set system modules (that is, modules in the JDK image), and the --add-exports, --add-reads, and --patch-module options if they modify system modules. (Use of --add-exports, --add-reads, and --patch-module is allowed for non-system modules, that is, modules that are not part of the JDK image.)
      • for any N, the -source and -target options, as those are automatically set to N.

      It is assumed that documented APIs will change only in major releases. For the legacy case where JAX-WS was updated from 2.0 to 2.1 in a minor release of JDK 6, JAX-WS 2.1 is considered the documented API.

      As a limitation of the --release implementation, the Unicode version of the given target platform is not used during compilation; the Unicode version of the current platform is used instead.

      Implementation

      For JDK N and --release M, M < N, signature data of the documented APIs of release M of the platform is needed. This data is stored in the $JDK_ROOT/lib/ct.sym file, which is similar, but not the same, as the file of the same name in JDK 8. The ct.sym file is a ZIP file containing stripped-down class files corresponding to class files from the target platform versions.

      For JDK N and --release N,the JDK's own image is used as the source of the class files to compile against. The list of observable modules is limited, however, to the documented modules and the jdk.unsupported module.

      Risks and Assumptions

      The JDK source-code repository needs to contain a description of the platform APIs of past releases. The size of the description may be considerable, and the resulting JDK builds will be larger. Care has been taken to reduce these space overheads as much as possible.

        Issue Links

          Activity

          Hide
          jlahoda Jan Lahoda added a comment -
          I've re-phrased the note on Unicode - thanks for the comment!
          Show
          jlahoda Jan Lahoda added a comment - I've re-phrased the note on Unicode - thanks for the comment!
          Hide
          dnsimon Douglas Simon added a comment - - edited
          We'd like to use the -release option in the Truffle project for building certain components to be deployed on 1.7. However, some of these components use sun.misc.Unsafe which is not made available in the ct.sym file provided in the current jdk9-ea build. Are there plans to add support to -release for popular internal APIs such as Unsafe from older JDKs?
          Show
          dnsimon Douglas Simon added a comment - - edited We'd like to use the -release option in the Truffle project for building certain components to be deployed on 1.7. However, some of these components use sun.misc.Unsafe which is not made available in the ct.sym file provided in the current jdk9-ea build. Are there plans to add support to -release for popular internal APIs such as Unsafe from older JDKs?
          Hide
          kbronkho Keimpe Bronkhorst added a comment -
          JEP 247 states: "The -release command line option is incompatible with numerous javac command line options". Would you please supply the list of incompatible options so I can filter them out when -release is used?
          Show
          kbronkho Keimpe Bronkhorst added a comment - JEP 247 states: "The -release command line option is incompatible with numerous javac command line options". Would you please supply the list of incompatible options so I can filter them out when -release is used?
          Hide
          jjg Jonathan Gibbons added a comment - - edited
          @Keimpe: Conceptually, the list is -source, -target and any options which might contribute to the platform class path, which is the bootclasspath and files in the extension directory and endorsed standards directory. In other words, anything that might conflict with the effect of -release.

          The javac code is as follows
          checkOptionAllowed(platformString == null,
                          option -> error("err.release.bootclasspath.conflict", option.getText()),
                          Option.BOOTCLASSPATH, Option.XBOOTCLASSPATH, Option.XBOOTCLASSPATH_APPEND,
                          Option.XBOOTCLASSPATH_PREPEND,
                          Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
                          Option.EXTDIRS, Option.DJAVA_EXT_DIRS,
                          Option.SOURCE, Option.TARGET);

          Translated, that means the options are
              -bootclasspath
              -Xbootclasspath
              -Xbootclasspath/a:
              -Xbootclasspath/p:
              -endorseddirs
              -Djava.endorsed.dirs
              -extdirs
              -Djava.ext.dirs
              -source
              -target
          Show
          jjg Jonathan Gibbons added a comment - - edited @Keimpe: Conceptually, the list is -source, -target and any options which might contribute to the platform class path, which is the bootclasspath and files in the extension directory and endorsed standards directory. In other words, anything that might conflict with the effect of -release. The javac code is as follows checkOptionAllowed(platformString == null,                 option -> error("err.release.bootclasspath.conflict", option.getText()),                 Option.BOOTCLASSPATH, Option.XBOOTCLASSPATH, Option.XBOOTCLASSPATH_APPEND,                 Option.XBOOTCLASSPATH_PREPEND,                 Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,                 Option.EXTDIRS, Option.DJAVA_EXT_DIRS,                 Option.SOURCE, Option.TARGET); Translated, that means the options are     -bootclasspath     -Xbootclasspath     -Xbootclasspath/a:     -Xbootclasspath/p:     -endorseddirs     -Djava.endorsed.dirs     -extdirs     -Djava.ext.dirs     -source     -target
          Hide
          jjg Jonathan Gibbons added a comment - - edited
          @Douglas: Currently there are no plans to include "popular internal APIs" such as Unsafe. What makes this a potentially interesting question is the recent decision to admit the existence of "critical internal APIs" in JDK 9 (see JEP 260, http://openjdk.java.net/jeps/260 ). That means when JDK 10 rolls around, we may need to support access to some of these APIs with "-release 9". What makes the interesting question much harder is, what about any internal API that was unofficially available in an old release like JDK 7, but which has since been replaced by an official API in a later release. That would require us to determine the critical internal API in older releases.

          For now, the recommended solution for anyone using internal API in older releases is to put the appropriate version of rt.jar on the bootclasspath.
          Show
          jjg Jonathan Gibbons added a comment - - edited @Douglas: Currently there are no plans to include "popular internal APIs" such as Unsafe. What makes this a potentially interesting question is the recent decision to admit the existence of "critical internal APIs" in JDK 9 (see JEP 260, http://openjdk.java.net/jeps/260 ). That means when JDK 10 rolls around, we may need to support access to some of these APIs with "-release 9". What makes the interesting question much harder is, what about any internal API that was unofficially available in an old release like JDK 7, but which has since been replaced by an official API in a later release. That would require us to determine the critical internal API in older releases. For now, the recommended solution for anyone using internal API in older releases is to put the appropriate version of rt.jar on the bootclasspath.

            People

            • Assignee:
              jlahoda Jan Lahoda
              Reporter:
              jlahoda Jan Lahoda
              Owner:
              Jan Lahoda
              Reviewed By:
              Alex Buckley, Brian Goetz, Jonathan Gibbons
              Endorsed By:
              Brian Goetz
            • Votes:
              0 Vote for this issue
              Watchers:
              13 Start watching this issue

              Dates

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