0 前言
编译插件用于编译项目的源代码。3.0 版本起,默认编译器是 javax.tools.JavaCompiler
(适用于 Java 1.6 及以上版本),用于编译 Java 源文件。如果希望强制插件使用 javac
,可以配置插件选项 forceJavacCompilerUse
。
目前默认 source
设置为 1.8
,target
设置也为 1.8
,无论运行 Maven 的 JDK 版本如何。这些默认值强烈建议通过设置 source
和 target
修改,具体方法请参考设置 Java 编译器的 -source 和 -target。
除了 javac
,还可以使用其他编译器,开发团队已经开始在 AspectJ、.NET 和 C# 上进行相应的工作。
有关 JDK javac
的更多信息,请访问:https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html。
1 目标
编译插件包含两个目标,这两个目标都已绑定到 Maven 生命周期中的相应阶段,因此会在其各自的阶段自动执行。
2 用法
有关如何使用编译插件的基本说明可以在用法页面中找到。下方列出了几个具体的使用案例示例。
如果您对插件的使用有疑问,请查阅常见问题解答,也可以随时联系用户邮件列表。邮件列表中的内容会被存档,可能已经包含了您问题的答案,因此浏览或搜索邮件存档也是不错的选择。
如果您认为插件缺少某个功能或存在缺陷,可以在我们的问题跟踪器中提交功能请求或错误报告。创建新问题时,请提供详细的描述,尤其是修复错误时,开发人员能够重现您的问题尤为重要。因此,附加完整的调试日志、POM 文件或小型示例项目将非常有帮助。当然,我们也欢迎补丁贡献,贡献者可以从我们的源代码库中获取项目,并在帮助 Maven 的指南中找到补充信息。
为帮助您更好地理解编译插件的一些用法,请参考以下示例:
3 使用不同的 JDK 进行编译
使用 Maven 工具链
使用不同 JDK 的最佳方式是通过工具链机制。若不使用工具链,在项目构建过程中,Maven 将使用 JDK 执行多个步骤,如编译 Java 源代码、生成 Javadoc、运行单元测试或签署 JAR 文件。每个插件都需要 JDK 工具来操作:如 javac
、javadoc
、jarsigner
等。工具链可以集中指定用于所有这些插件的 JDK 路径,而与运行 Maven 本身的 JDK 无关。
置此功能,参阅工具链使用指南,该指南介绍 Maven 工具链插件 的使用方法。
通过 maven-toolchains-plugin,您可以为所有相关的 Maven 插件配置一个默认的 JDK 工具链。从 maven-compiler-plugin 3.6.0 版本起,使用 Maven 3.3.1 及更高版本时,插件还可以单独使用其自己的工具链配置,这在不同的执行块需要使用不同的 JDK(例如测试源代码需要不同的编译器)时非常有用。
配置编译插件
不使用工具链情况,仍可为编译插件指定要使用的 JDK。这种配置仅适用于编译插件,不会影响其他插件。
可用 compilerVersion
参数指定插件使用的编译器版本,不过要使其生效,还需要将 fork
设置为 true
。例如:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<verbose>true</verbose>
<fork>true</fork>
<executable><!-- path-to-javac --></executable>
<compilerVersion>1.3</compilerVersion>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
为避免硬编码 executable
的文件系统路径,可用属性。如:
<executable>${JAVA_1_4_HOME}/bin/javac</executable>
每位开发者可在 settings.xml 中定义该属性或通过设置环境变量,确保构建的可移植性。
<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>
如用不同 JDK 进行构建,可能希望自定义 jar 文件的 manifest 文件。
4 使用 -source 和 -target javac 选项进行编译
设置 Java 编译器的 -source
和 -target
有时需要将项目编译为与当前 JDK 不同的版本。javac
可接受 -source
和 -target
命令,编译插件也可以配置这些选项以便在编译时使用。
如若希望使用 Java 8 语言特性(-source 1.8
),并希望编译后的类与 JVM 1.8 兼容(-target 1.8
),可以添加以下两个属性(这些是插件参数的默认属性名称):
<project>
[...]
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
[...]
</project>
或直接配置插件:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
仅设置 target
选项并不能保证代码能在指定版本的 JRE 上运行。问题在于可能无意中使用了较新 JRE 才有的 API,这会导致代码在运行时出现链接错误。为避免此问题,可以配置编译器的引导类路径来匹配目标 JRE,或使用 Animal Sniffer Maven 插件 验证代码不会使用不兼容的 API,更好的方法是使用自 JDK 9 起支持的 release
选项。此外,设置 source
选项并不保证代码能在指定版本的 JDK 上成功编译。如需使用与运行 Maven 不同的 JDK 编译代码,请参考使用不同 JDK 进行编译示例。
5 使用 --release javac 选项进行编译(自 JDK 9 支持)
从 JDK 9 开始,javac
可接受 --release
选项来指定构建项目所需的 Java SE 版本。例如,您已安装并在 Maven 中使用 JDK 11,但希望项目针对 Java 8 进行构建。--release
选项确保代码按照指定版本的编程语言规则进行编译,生成的类文件符合该版本的公共 API。与 -source
和 -target
选项 不同,编译器会检测并在使用不支持的 API 时生成错误。
自编译插件 3.6 版本起,可以通过属性来设置此选项:
<project>
[...]
<properties>
<maven.compiler.release>8</maven.compiler.release>
</properties>
[...]
</project>
或者直接配置插件:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<release>8</release>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
注意:release
参数的值遵循 Java 9 起采用的新版本命名方案,因此版本号不再以 1.x 开头。此外,支持的 release
目标包括当前 JDK 版本及少量较早版本。
在 JDK 8 上的使用
在 JDK 8 上不支持 --release
选项。为了在 JDK 8 和 JDK 9 或更高版本中构建面向 Java 8 的项目,需有条件地使用 --release
选项。
若编译插件版本低于 3.13.0
或编译器 ID 不为 javac
时则需要条件参数化。
可以通过配置文件实现:
<project>
[...]
<profiles>
[...]
<profile>
<id>set-compiler-release</id>
<activation>
<jdk>[9,)</jdk>
</activation>
<properties>
<maven.compiler.release>8</maven.compiler.release>
</properties>
</profile>
[...]
</profiles>
[...]
</project>
自编译插件 3.13.0
版本及默认 javac
编译器 ID 开始,不再需要条件参数化。release
参数仅在 Java 9 或更高版本中有效,否则将传递 source
和 target
参数给编译器。
因此,可以直接配置为:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<release>8</release>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
6 使用内存分配增强功能进行编译
编译器插件接受 meminitial
和 maxmem
的配置。您可以按照以下示例将初始内存大小设置为 128MB,并将最大内存使用量设置为 512MB:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<fork>true</fork>
<meminitial>128m</meminitial>
<maxmem>512m</maxmem>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
7 传递编译器参数
有时,您需要传递编译器参数,这些参数并不被编译器插件本身处理,但被所选的 compilerId
支持。对于此类参数,请使用编译器插件的 compilerArgs
参数。以下示例向 javac
编译器传递编译器参数:
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<compilerArgs>
<arg>-verbose</arg>
<arg>-Xlint:all,-options,-path</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
参考: