JEP 247: Compile for Older Platform Versions

OwnerJan Lahoda
Created2014/09/10 16:56
Updated2017/05/16 20:56
TypeFeature
StatusClosed / Delivered
Componenttools / javac
ScopeJDK
Discussioncompiler dash dev at openjdk dot java dot net
EffortM
DurationL
Priority3
Reviewed byAlex Buckley, Brian Goetz, Jonathan Gibbons
Endorsed byBrian Goetz
Release9
Issue8058150

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, 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:

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.