Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the --release flag in the Java 9 compiler?

Tags:

java

java-9

javac

Java 9's javac has a new flag --release:

> javac --help ...  --release <release>     Compile for a specific VM version. Supported targets: 6, 7, 8, 9 

How is it different from -source and -target flags? Is it just a shortcut for -source X -target X?

like image 631
ZhekaKozlov Avatar asked Mar 29 '17 19:03

ZhekaKozlov


People also ask

What is the name of the command used for compiling the Java module?

The javac command reads source files that contain module, package and type declarations written in the Java programming language, and compiles them into class files that run on the Java Virtual Machine. The javac command can also process annotations in Java source files and classes.

What is the difference between javac and Java?

javac compiles the code and makes it into an executable format. java runs the code you just built. Hope this helps!

Which command compiles a Java program in which the class is defined as Hello?

The javac command reads class and interface definitions, written in the Java programming language, and compiles them into bytecode class files.


2 Answers

Not exactly.

JEP 247: Compile for Older Platform Versions defines this new command-line option, --release:

We defined a new command-line option, --release, which automatically configures the compiler to produce class files that will link against an implementation of the given platform version. For the platforms predefined in javac, --release N is equivalent to -source N -target N -bootclasspath <bootclasspath-from-N>. (emphasis mine)

So no, it is not equivalent to -source N -target N. The reason for this addition is stated in the "Motivation" section:

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 specified platform version.

In short, specifying the source and target options are not sufficient for cross-compilation. Because javac, by default, compiles against the most recent of the platform APIs, they can't be guaranteed to run on older versions. You also need to specify the -bootclasspath option corresponding to the older version to cross-compile correctly. This would include the correct API version to compile against and allow for execution on older version. Since it was very often forgotten, it was decided to add one command line option which did all the necessary things to correctly cross-compile.

Further reading in the mailing list and Oracle Docs. The original bug was filed here. Note that since the integration of this option, JDK builds have come bundled with descriptions of the platform APIs of older releases, mentioned under section "Risks and Assumptions". That means you don't need the older version installed on your machine for cross-compilation to work.

like image 118
Andrew Li Avatar answered Sep 28 '22 07:09

Andrew Li


--release X is more than just a shortcut to -source X -target X because -source and -target are not sufficient to safely compile to an older release. You also need to set a -bootclasspath flag which must correspond to the older release (and this flag is often forgotten). So, in Java 9 they made a single --release flag which is a replacement for three flags: -source, -target and -bootclasspath.

So, this is an example of compiling to Java 1.7:

javac --release 7 <source files> 

Note that you don't even need to have JDK 7 installed on your computer. JDK 9 already contains the needed information to prevent you from accidental linking to symbols that did not exist in JDK 7.

Another important difference is that you can only use public APIs when compiling with --release:

> javac --add-exports java.base/sun.invoke=ALL-UNNAMED --release 11 Main.java error: exporting a package from system module java.base is not allowed with --release 1 error 

If you want to use internal APIs, you have to remove the option --release:

> javac --add-exports java.base/sun.invoke=ALL-UNNAMED Main.java 

or

> javac --add-exports java.base/sun.invoke=ALL-UNNAMED -source 11 -target 11  Main.java 
like image 31
ZhekaKozlov Avatar answered Sep 28 '22 07:09

ZhekaKozlov