JEP 247: Compile for Older Platform Versions
Owner | Jan Lahoda |
Type | Feature |
Scope | JDK |
Status | Closed / Delivered |
Release | 9 |
Component | tools / javac |
Discussion | compiler dash dev at openjdk dot java dot net |
Effort | M |
Duration | L |
Reviewed by | Alex Buckley, Brian Goetz, Jonathan Gibbons |
Endorsed by | Brian Goetz |
Created | 2014/09/10 16:56 |
Updated | 2023/05/18 23:47 |
Issue | 8058150 |
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.