I am creating a set of libraries for in-house use, and I have a reactor pom setup to build all these libraries.
I want to be able to build them all at once, with one command.
However, the contexts where the libraries will be used have different base Java runtimes.
Because I want to build them all at once I need to have the Java version I run this build as the most recent Java version I'm targeting.
However, while I know that I can set the compiler target in each of my projects to match the java version where that project will be used how can I guarantee that I won't inadvertently use a method or class in that project that is only available in the more recent version of Java I'm using to build these libraries?
javac
9 introduced a --release
flag that will, to quote the documentation, "Compile for the specified Java SE release".
The maven-compiler-plugin
also supports this feature, and allows you to use the <release>
tag in its configuration to pass a value down to the Java compiler.
For example, you could configure your compiler plugin to compile for Java 9:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<encoding>UTF8</encoding>
<release>9</release>
</configuration>
</plugin>
Alternatively, you can configure this behavior by setting the built-in maven.compiler.release
property:
<properties>
<maven.compiler.release>9</maven.compiler.release>
</properties>
Now let's see what it does.
Consider, for example, that you have a piece of code that uses List
's addFirst
method, introduced in Java 21:
List<Integer> myList = new ArrayList<>();
myList.addFirst(1);
When compiling it with this configuration, it will explicitly be compiled to be compatible with Java 9's API, and the compilation will fail:
[INFO] --- compiler:3.13.0:compile (default-compile) @ samplejava ---
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 1 source file with javac [debug release 9] to target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /Users/mureinik/src/samplejava/src/main/java/org/example/Main.java:[9,15] cannot find symbol
symbol: method addFirst(int)
location: variable myList of type java.util.List<java.lang.Integer>
[INFO] 1 error
This is despite using a modern Java version that most certainly has that method in its JDK:
ā samplejava mvn --version
Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937)
Maven home: /opt/homebrew/Cellar/maven/3.9.9/libexec
Java version: 23.0.2, vendor: Homebrew, runtime: /opt/homebrew/Cellar/openjdk/23.0.2/libexec/openjdk.jdk/Contents/Home
Default locale: en_IL, platform encoding: UTF-8
OS name: "mac os x", version: "15.5", arch: "aarch64", family: "mac"
EDIT:
For completion's sake - the --release
flag supports Java versions 8 and above. If you need to support an older Java version, you can use the Animal Sniffer Maven Plugin.