-
Notifications
You must be signed in to change notification settings - Fork 0
Incompatible changes
This page describes behaviors of the Maven compiler plugin 4 that changed in incompatibles way compared to versions 3.
Some projects building successfully with version 3 of maven-compiler-plugin
may fail with version 4 because of those changes.
This page describes corrections that can be applied to projects for fixing those build failures.
As a general rule, this new Maven plugin does not modify the compiler options specified in the configuration.
This policy may break projects that specify the <release>
option together with <source>
and <target>
.
The previous version of the plugin applied some heuristic rules for deciding which options to pass to the Java compiler.
The new version passes all options verbatim, which may result in the following message from the javac
compiler:
option --source cannot be used together with --release
Removes the <source>
and <target>
configuration parameters.
They may be specified indirectly through the maven.compiler.source
and maven.compiler.target
properties.
If those configuration parameters or properties are inherited from a super-POM that cannot be modified,
clear the <source>
and <target>
parameters as below:
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source/>
<target/>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
Problems may occur if a Java modular project is defined in the Maven 3 way
(i.e., like a non-modular project with only the addition of a module-info.java
file),
if the module name is a single name without .
separator
(for example, foo
or bar
but not foo.bar
) and that name is identical to a package name.
It is because in such case, the hack implemented in the Maven compiler plugin for Maven 3 compatibility
become confused about whether a directory named foo
represents the module or the package.
Define the Java modular project in the Maven 4 way.
Keep in mind that it will change the layout of the target/classes
directory.
Example:
<build>
<sources>
<source>
<module>foo</module>
<directory>src/java/main</directory>
</source>
</sources>
</build>
If a dependency does not declare explicitly whether the JAR file should be placed on the class-path
or on the module-path, the Maven plugin uses heuristic rules for making its own decision.
Those rules are not obvious, and the selected option is not always appropriate for the project.
The results may sometime be different between this version and the previous version of maven-compiler-plugin
.
Some JAR files may placed on the class-path when they were previously on the module-path, or conversely.
By default, a dependency is placed on --module-path
if the project is itself modularized
(i.e., contains a module-info.java
) and one of the following conditions is true:
- The JAR contains a
module-info.class
entry. - The JAR contains a
META-INF/MANIFEST.MF
entry with anAutomatic-Module-Name
attribute.
In all other cases, the dependency is placed on --class-path
.
This default behavior may be adjusted in future Maven plugin versions depending on experience.
Developers are strongly encouraged to specify explicitly where they want their non-modular JAR files to appear in a modular project.
It can be done by setting the type of a dependency to modular-jar
or classpath-jar
.
Example:
<project>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.0.24</version>
<type>modular-jar</type>
</dependency>
</dependencies>
</project>
Note that specifying the dependency type is usually not needed in other cases (e.g., non-modular project, or dependencies that are already modular). It should not be needed neither for dependencies with the runtime scope. However, it may be a good practice to be explicit anyway for more guarantees.
If a non-modular dependency is forced to the modular-jar
type,
Java will automatically infer a module name from the file name.
That name can be shown by the jar --describe-module
command.
For example, the following command shows the name of above plexus-utils
dependency on a Unix system:
jar --describe-module --file ~/.m2/repository/org/codehaus/plexus/plexus-utils/3.0.24/plexus-utils-3.0.24.jar
The command output contains [email protected] automatic
.
That module name must be declared in the module-info.java
file.
module my.module {
requires plexus.utils;
}
Conversely, if a dependency is forced to the classpath-jar
type,
then the module-info.java
is not modified.
Instead, the pom.xml
file should have the following configuration
(replace my.module
by the actual project module name):
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>--add-reads</arg>
<arg>my.module=ALL-UNNAMED</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
The META-INF/jpms.args
file is no longer generated.
The closest match is target/javac.args
which is generated if the build fails,
or if the --verbose
option was provided to the mvn
command.