How to set specific Java version to Maven?
Maven uses the JAVA_HOME
parameter to find which Java version it is supposed to run. I see from your comment that you can't change that in the configuration.
- You can set the
JAVA_HOME
parameter just before you start maven (and change it back afterwards if need be). - You could also go into your
mvn
(non-windows)/mvn.bat
/mvn.cmd
(windows) and set your java version explicitly there.
Specify JDK for Maven to use
So bottom line is, is there a way to specify a jdk for a single invocation of maven?
Temporarily change the value of your JAVA_HOME
environment variable.
Maven is using wrong java version
Following is a list of steps I use to troubleshoot this kind of issues:
- Linux usually works with
alternatives
to ensure proper default Java environment is used. Similar to:
$ alternatives --config java
There are 2 programs which provide 'java'.
Selection Command
-----------------------------------------------
+ 1 java-1.7.0-openjdk.x86_64 (/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.191-2.6.15.4.el7_5.x86_64/jre/bin/java)
* 2 java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-3.b13.el7_5.x86_64/jre/bin/java)
Try also for javac
as it may not be configured the same way:
$ alternatives --config javac
- For your
maven
instance,JAVA_HOME
should be enough.
Your output of mvn -version
testifies that you have configured it correctly. Remove your Java from your PATH
to ensure JAVA_HOME
and mvn
will find the correct one.
- The
pom.xml
can also configure the required compiler, similar to:
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
- Another thing may be that you're not using the same ENV (different terminals may not have the same environment variables exported - I presume you being on CentOS, you already encountered this). You have to exit the terminal and get back in to allow the default variables to take effect.
You encounter this usually when different JRE vs JDK are used ( more: maven installation has runtime as JRE instead of JDK )
Specifying Java version in maven - differences between properties and compiler plugin
How to specify the JDK version?
Use any of three ways: (1) Spring Boot feature, or use Maven compiler plugin with either (2) source
& target
or (3) with release
.
Spring Boot
<java.version>
is not referenced in the Maven documentation.
It is a Spring Boot specificity.
It allows to set the source and the target java version with the same version such as this one to specify java 1.8 for both :
1.8
Feel free to use it if you use Spring Boot.
maven-compiler-plugin
with source
& target
- Using
maven-compiler-plugin
ormaven.compiler.source
/maven.compiler.target
properties are equivalent.
That is indeed :
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
is equivalent to :
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
according to the Maven documentation of the compiler plugin
since the <source>
and the <target>
elements in the compiler configuration use the properties maven.compiler.source
and maven.compiler.target
if they are defined.
source
The
-source
argument for the Java compiler.
NOTE: Since 3.8.0 the default value has changed from 1.5 to 1.6. Since 3.9.0 the default value has changed from 1.6 to 1.7
Default value is: 1.7.
User property is:maven.compiler.source
.
target
The
-target
argument for the Java compiler.
NOTE: Since 3.8.0 the default value has changed from 1.5 to 1.6. Since 3.9.0 the default value has changed from 1.6 to 1.7
Default value is:1.6
.
User property is:maven.compiler.target
.
About the default values for source
and target
, note that
since the 3.8.0
of the maven compiler, the default values have changed from 1.5
to 1.6
.
maven-compiler-plugin
with release
instead of source
& target
The maven-compiler-plugin
3.6
and later versions provide a new way :
org.apache.maven.plugins
maven-compiler-plugin
3.8.0
9
You could also declare just :
<properties>
<maven.compiler.release>9</maven.compiler.release>
</properties>
But at this time it will not work as the maven-compiler-plugin
default version you use doesn't rely on a recent enough version.
The Maven release
argument conveys release
: a new JVM standard option that we could pass from Java 9 :
Compiles against the public, supported and documented API for a
specific VM version.
This way provides a standard way to specify the same version for the source
, the target
and the bootstrap
JVM options.
Note that specifying the bootstrap
is a good practice for cross compilations and it will not hurt if you don't make cross compilations either.
Which is the best way to specify the JDK version?
The first way (<java.version>
) is allowed only if you use Spring Boot.
For Java 8 and below :
About the two other ways : valuing the maven.compiler.source
/maven.compiler.target
properties or using the maven-compiler-plugin
, you can use one or the other. It changes nothing in the facts since finally the two solutions rely on the same properties and the same mechanism : the maven core compiler plugin.
Well, if you don't need to specify other properties or behavior than Java versions in the compiler plugin, using this way makes more sense as this is more concise:
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
From Java 9 :
The release
argument (third point) is a way to strongly consider if you want to use the same version for the source and the target.
What happens if the version differs between the JDK in JAVA_HOME and which one specified in the pom.xml?
It is not a problem if the JDK referenced by the JAVA_HOME
is compatible with the version specified in the pom but to ensure a better cross-compilation compatibility think about adding the bootstrap
JVM option with as value the path of the rt.jar
of the target
version.
An important thing to consider is that the source
and the target
version in the Maven configuration should not be superior to the JDK version referenced by the JAVA_HOME
.
A older version of the JDK cannot compile with a more recent version since it doesn't know its specification.
To get information about the source, target and release supported versions according to the used JDK, please refer to java compilation : source, target and release supported versions.
How handle the case of JDK referenced by the JAVA_HOME is not compatible with the java target and/or source versions specified in the pom?
For example, if your JAVA_HOME
refers to a JDK 1.7 and you specify a JDK 1.8 as source and target in the compiler configuration of your pom.xml, it will be a problem because as explained, the JDK 1.7 doesn't know how to compile with.
From its point of view, it is an unknown JDK version since it was released after it.
In this case, you should configure the Maven compiler plugin to specify the JDK in this way :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerVersion>1.8</compilerVersion>
<fork>true</fork>
<executable>D:\jdk1.8\bin\javac</executable>
</configuration>
</plugin>
You could have more details in examples with maven compiler plugin.
It is not asked but cases where that may be more complicated is when you specify source but not target. It may use a different version in target according to the source version. Rules are particular : you can read about them in the Cross-Compilation Options part.
Why the compiler plugin is traced in the output at the execution of the Maven package
goal even if you don't specify it in the pom.xml?
To compile your code and more generally to perform all tasks required for a maven goal, Maven needs tools. So, it uses core Maven plugins (you recognize a core Maven plugin by its groupId
: org.apache.maven.plugins
) to do the required tasks : compiler plugin for compiling classes, test plugin for executing tests, and so for... So, even if you don't declare these plugins, they are bound to the execution of the Maven lifecycle.
At the root dir of your Maven project, you can run the command : mvn help:effective-pom
to get the final pom effectively used. You could see among other information, attached plugins by Maven (specified or not in your pom.xml), with the used version, their configuration and the executed goals for each phase of the lifecycle.
In the output of the mvn help:effective-pom
command, you could see the declaration of these core plugins in the <build><plugins>
element, for example :
...
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>default-clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>default-testResources</id>
<phase>process-test-resources</phase>
<goals>
<goal>testResources</goal>
</goals>
</execution>
<execution>
<id>default-resources</id>
<phase>process-resources</phase>
<goals>
<goal>resources</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<executions>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
...
You can have more information about it in the introduction of the Maven lifeycle in the Maven documentation.
Nevertheless, you can declare these plugins when you want to configure them with other values as default values (for example, you did it when you declared the maven-compiler plugin in your pom.xml to adjust the JDK version to use) or when you want to add some plugin executions not used by default in the Maven lifecycle.
Setting the Java Version in Maven with system Java version as 11.0
Setting java.version
in the POM <properties>
section does not change the Java version used to compile with the maven-compiler-plugin
. It is instead used by Spring Boot (see Specifying java version in maven - differences between properties and compiler plugin for a related discussion).
Your build is still using the JDK 11 installed on your machine (this is reflected by the manifest attribute Build-Jdk: 11.0.2
), however, your code is actually compiled with source and target of Java 8. JDK 11 knows how to compile against earlier versions like JDK 8, so your build is working fine as expected.
How to change maven java home
If you are in Linux, set JAVA_HOME using syntax export JAVA_HOME=<path-to-java>
. Actually it is not only for Maven.
Using specific Maven library that compiles with specific Java version
First read the release notes for hsqldb:
21 March 2021 - version 2.6.0
-- version 2.6.0 jar requires JRE 11 or later - tested up to Java 16 RC
-- version 2.6.0 alternative jar requires JRE 8 or later
The documentation clearly states that 2.6.0 needs an alternative jar to work with jdk8.
Inpect the hsqldb maven repo to verify that there is an alternative jar provided for jdk8: hsqldb-2.6.1-jdk8.jar
To import it with maven, you need to use a classifier
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.6.1</version>
<classifier>jdk8</classifier>
</dependency>
Related Topics
Program Freezes During Thread.Sleep() and with Timer
How to Convert a Java 8 Stream to an Array
Java Synchronized Method Lock on Object, or Method
How to Set Java_Home Environment Variable on MAC Os X 10.9
I Get Exception When Using Thread.Sleep(X) or Wait()
Map Enum in JPA with Fixed Values
Ignore Duplicates When Producing Map Using Streams
Closing Jdbc Connections in Pool
How to Create an Array of Arraylists
How to Use the Instanceof Operator in a Switch Statement
How to View the SQL Queries Issued by JPA
How to Create Immutable Objects in Java
Using Bigdecimal to Work with Currencies
When Overriding a Method, Why How to Increase Access But Not Decrease It
Spring: How to Inject an Httpservletrequest into a Request-Scoped Bean
Spring Boot - Cannot Determine Embedded Database Driver Class for Database Type None