Table of Contents
- 1. What is Maven Compiler Plugin
- 2. Default Configuration
- 3. Common Compilation Error
- 4. Custom Configuration Java 8 or Earlier
- 5. Custom Configuration Java 9 and Beyond
1. What is Maven Compiler Plugin
The ‘Maven Compiler Plugin’ or more commonly known as ‘Maven Java Compiler’ is used to compile the source code of your project/application.
Internally this plugin uses the standard ‘javac’ compiler (JDK) and as of version 3.0 of this plugin the default compiler is javax.tools.JavaCompiler
Unlike other Maven plugins, the ‘maven compiler plugin’ is ‘in-built’ and ‘implicit’ in nature. This plugin has two goals, which are already bound to specific phases of the default lifecycle:
- compile: compile main source files
- testCompile: compile test source files
As mentioned earlier, the maven compiler plugin is called implicitly and automatically by the maven lifecycle in the appropriate phase. Hence you don´t necessarily need to define it inside ‘pom.xml’ it shall be downloaded and executed automatically by maven as and when required. However, we can certainly define and configure custom behavior and attributes for this plugin by specifying it in the ‘pom.xml’.
2. Default Configuration
As per the default behavior, the ‘maven compiler plugin’ compiles source code compatible with Java 5 (also written as Java 1.5), irrespective of the JDK installed on your machine. However, with custom configuration in your ‘pom.xml’ you can override this behavior and specify your own version of compiler and compatibility version.
Note: The java version used to launch Maven itself (Maven runtime) can be set to a different version than the version used for compiling your source code or project. This can be done using custom configuration in your pom.xml as explained in below examples.
You can find out java version for ‘Maven runtime’ by typing the command ‘mvn -v’ or ‘mvn -version’
3. Common Compilation Error
While starting with Maven projects, it is very common to encounter the below error associated with this plugin. This is nothing but the default behavior as mentioned in the above paragraph and can be rectified by using one of the below mentioned custom configurations for your maven java compiler.
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] Source option 5 is no longer supported. Use 6 or later.
[ERROR] Target option 1.5 is no longer supported. Use 1.6 or later.
[INFO] 2 errors
[INFO] -------------------------------------------------------------
4. Custom Configuration Java 8 or Earlier
If you are using Java 8 or earlier, you can set the Maven Java Compiler version in your POM file using one of the following three methods:
- Using POM Properties
- Using -source and -target values in compiler configuration
- Using compilerVersion in compiler configuration
Let us start with a standard bare-bone ‘pom.xml’ file and insert our custom configuration for ‘Maven Compiler Plugin’ eventually by three different methods.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.testoxide</groupId> <artifactId>maven-quick-start</artifactId> <version>1.0</version> </project>
4.1. Configure using POM Properties
In this method rather than tweaking the ‘maven compiler’ configuration or ‘build’ configuration’ directly, you can use the POM properties to set the compiler (JDK) versions.
This is the most simple but probably least reliable way. However, which option works best for you depends on the setup of your project and specific requirements i.e. depend on a case by case basis.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.testoxide</groupId> <artifactId>maven-quick-start</artifactId> <version>1.0</version> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> </project>
Using the above configuration should give you output classes both compiled and compatible with the specified java (compiler) version which is Java 8 in this case.
4.2. Configure using -source & -target
Another, preferred way for forcing a specific compiler version is by modifying the default parameter values of ‘-source’ and ‘target’ directly in the plugin settings as below.
Here we are setting the JDK/JRE version for both source and target to 1.8
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.testoxide</groupId> <artifactId>maven-quick-start</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
4.3. Configure using ‘compilerVersion’
You can use this method to compile your code with a ‘very specific’ JDK version, even if it is different than the one used to launch Maven itself. This is probably the most precise of all methods.
Here ‘compilerVersion’ parameter can be used as part of ‘build configuration’ to specify the version of the compiler that the plugin will use. However, you also need to set fork to true for this to work
Using the below ‘POM’ configuration, it is still possible to tell the ‘Maven Compiler Plugin’ the specific JDK to use during compilation. But such configuration will be specific to this plugin, and will not affect others.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.testoxide</groupId> <artifactId>maven-quick-start</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <verbose>true</verbose> <fork>true</fork> <executable><!-- path-to-javac --></executable> <compilerVersion>1.3</compilerVersion> </configuration> </plugin> </plugins> </build> </project>
4.3.1. Improvise – Use variable for Path
In the above ‘pom.xml’ snippet, rather than hardcoding the path to java compiler, you can replace it with a variable. We can do so by using the following property: <executable>${JAVA_1_4_HOME}/bin/javac</executable>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.testoxide</groupId> <artifactId>maven-quick-start</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <verbose>true</verbose> <fork>true</fork> <executable>${JAVA_1_8_HOME}/bin/javac</executable> <compilerVersion>1.8</compilerVersion> </configuration> </plugin> </plugins> </build> </project>
The best part of using the above property is that different users can specify their own values for this property in their ‘settings.xml’ file, keeping your project portable for different users and machine configurations.
<settings> [...] <profiles> [...] <profile> <id>compiler</id> <properties> <JAVA_1_4_HOME>C:\Program Files\Java\j2sdk1.4.2_09</JAVA_1_4_HOME> </properties> </profile> </profiles> [...] <activeProfiles> <activeProfile>compiler</activeProfile> </activeProfiles> </settings>
4.3.2. Improvise – Pass args to compiler
If you wish to pass some arguments to the maven java compiler, you can do so in two ways.
Method 1: Using <configuration> element
You can pass the compiler arguments inside the ‘configuration’ part of the compiler plugin itself. A very common example is to pass min and max memory values as below.
Here we are passing the following arguments related to max and min memory to the compiler:
<meminitial>128m</meminitial> <maxmem>512m</maxmem> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.testoxide</groupId> <artifactId>maven-quick-start</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <verbose>true</verbose> <fork>true</fork> <executable>${JAVA_1_8_HOME}/bin/javac</executable> <compilerVersion>1.3</compilerVersion> <meminitial>128m</meminitial> <maxmem>512m</maxmem> </configuration> </plugin> </plugins> </build> </project>
Method 2: Using explicit <compilerArgs>
You should use ‘<compilerArgs>’ element to pass specific compiler arguments that are not handled by the Compiler Plugin itself but are supported by the compilerId selected. For such arguments, use the Compiler Plugin’s <compilerArgs> parameter.
The following example passes compiler arguments to the javac compiler:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.testoxide</groupId> <artifactId>maven-quick-start</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <verbose>true</verbose> <fork>true</fork> <executable>${JAVA_1_8_HOME}/bin/javac</executable> <compilerVersion>1.3</compilerVersion> <meminitial>128m</meminitial> <maxmem>512m</maxmem> <compilerArgs> <arg>-verbose</arg> <arg>-Xlint:all,-options,-path</arg> <arg>-Xmaxerrs</arg> <arg>1000</arg> <arg>-J-Duser.language=en_us</arg> </compilerArgs> </configuration> </plugin> </plugins> </build> </project>
5. Custom Configuration Java 9 and Beyond
Starting from JDK 9, we can use a new command-line option i.e. ‘-release’ which is accepted by the javac executable and can be used to specify against which Java SE release you want to build the project.
This new argument replaces the traditional ‘source’ and ‘target’ properties used for Java 8 or earlier and will automatically configure the compiler to produce class files compatible with the given platform version which should be Java 9 or above. You can implement this ‘-release’ value in the following two ways :
5.1. Configure using POM Properties
In this method, you can specify the Java compiler version using the ‘maven.compiler.release’ element inside the POM Properties. Here is how the Maven Java compiler release element look inside pom properties:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.testoxide</groupId> <artifactId>maven-quick-start</artifactId> <version>1.0</version> <properties> <maven.compiler.release>11</maven.compiler.release> </properties> </project>
5.2. Configure using plugin <configuration>
In this method, instead of the source and target properties (as mentioned in section 4.2 above), you need to use the ‘-release‘ property inside the Maven Java compiler plugin’s ‘<configuration>’ element. Given below is the snippet for such implementation:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.testoxide</groupId> <artifactId>maven-quick-start</artifactId> <version>1.0</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <release>11</release> </configuration> </plugin> </plugins> </build> </project>
The value in the ‘-release’ parameter follows the new version naming scheme adopted since Java 9. As such, the release number does not start with 1.x anymore.
Also note that ‘-release’ parameter is available for maven-compiler-plugin starting 3.6 version