Week 133 — How can one use a newer JDK to compile applications for an older Java version?
Question of the Week #133
How can one use a newer JDK to compile applications for an older Java version?
5 Replies
Java allows running application compiled for an older Java version using a newer JDK like any other application. If code is compiled with JDK 8, it can typically still be used with JDK 21 (unless it uses internal APIs that have been change or removed) without any modifications.
Similarly, it is possible to use a newer JDK to compile applications for older JDKs. To do this, the classes to compile must not use any language or features that were introduced after the Java version to compile to. If that's the case, the
--release
option followed by the Java version to compile to can be added to the javac
command. For example, to use a JDK 21 installation to compile an application for JDK 17, the command javac --release 17 YourClass.java
(or similar) can be used. The class can then be used with JDK 17 or later.
Another option is the use of --source
and --target
instead of --release
. The --source
argument specifies the language level for the Java classes to compile while the --target
option specifies the version of the class files to compile to (i.e. the compiled classes can be used with these JDK versions or newer). If thse options are present, the --source
argument must refer to a lower Java version than --target
.
While --release
checks which parts of the JDK standard libraries are used and only allows using what was available in the Java version to compile to. This is not done with --source
/--target
which allows using API features not present in the version to compile to. This can result in the compiled types being unusable with the specified version. For this reason, --release
should typically be preferred over --source
/--target
📖 Sample answer from dan1st
The Java compiler,
javac
, provides 3 flags that can control the supported language level of the source along with the generated bytecode level of the compiled class files:
- --source
- Tells the compiler to allow Java syntax up to the specified version. In JDK versions prior to 13, the flag was -source
; more recent versions still support this flag for backwards compatibility.
- --target
- Tells the compiler to generate bytecode that is compatible with the specified JVM version. In JDK versions prior to 13, the flag was -target
; more recent versions still support this flag for backwards compatibility.
- --release
- Introduced in JDK 9, this flag combines the functionality of --source
& --target
, but it also does more. It ensures that the code only uses Java Platform APIs that are present in the specified release. This addresses a bug where code compiled with an older --source/--target
specification may still not run on the older JRE. This flag cannot be used in conjunction with --source
or --target
.Submission from dangerously_casual
There are situations where you need to ensure your code runs on older Java versions while using a newer JDK for development.
This is called cross-compilation, and java provides compiler options to achieve this backward compatibility.
Modern (JDK 9+) (Recommended)
Use of
--release
flag is recommended for JDK 9+, javac --release 8 MyClass.java
.
--release
flag ensures full compability by compiling against the specified target's standard libraries. It replaces the combination of the three legacy flags, -target -source -boothclasspath
, but is more stricter and easy to use.
Legacy (before JDK 9)
Compilation Flags:
- -target
: This specifies the target Java version for the compiled bytecode, javac -target 8 MyClass.java
.
- -source
: This tells the compiler which version of Java source code you're using, javac -source 8 -target 8 MyClass.java
- -bootclasspath
: This overrides the default Java standard library used by javac
during compilation. javac -source 8 -target 8 -bootclasspath /path/to/java8/rt.jar MyClass.java
.
Notes:
- You cannot set a -source
version higher than the -target
version.
- Without -bootclasspath
, you may accidentally use newer APIs that don’t exist in the target JDK, which compiles fine but crashes at runtime.⭐ Submission from daysling
javac --release x or javac --source x --target x
Submission from fakl
javac --release 8 -d out MyApp.java
Submission from karlas1.