javac source/target参数与Maven文档表述冲突?兼问release参数作用
关于javac的--source、--target与Maven编译插件的说明冲突问题
一、两者表述均正确,仅侧重点不同
javac官方文档是从编译规则与类文件版本的基础功能层面描述:
--source:强制编译器按照指定Java版本的语法规则校验源码,例如用--source=8编译时,不允许使用Java 10才引入的var关键字--target:生成对应Java版本的字节码文件(如--target=8生成的class文件版本号为52.0)
而Maven编译插件的说明是从实际运行兼容性的场景出发——单独设置source或target,无法限制代码对高版本JDK API的调用,因此不能完全保证跨版本的编译/运行可靠性。
二、示例解释合理性
示例1:仅设置--source=8和--target=8,但调用高版本API
假设用JDK 17编译,仅配置--source=8 --target=8,但源码中调用了Java 11新增的API:
public class TestCompat { public static void main(String[] args) { // Java 11新增的String.isBlank()方法 System.out.println("".isBlank()); } }
- 编译阶段:
--source=8仅校验语法,String.isBlank()属于API调用,语法符合Java 8规范,因此编译可通过,生成的class文件为Java 8版本 - 运行阶段:将该class文件放到Java 8的JRE上运行时,会抛出
NoSuchMethodError——因为Java 8的String类中不存在isBlank()方法
这正好对应Maven文档的说明:仅设置target保证了字节码版本,但无法限制代码调用高版本API,导致低版本JRE无法运行。
示例2:仅设置--source的局限性
如果用JDK 17编译,仅设置--source=8不设置target,编译器会默认生成JDK 17版本的字节码(版本号61.0),将其放到Java 8的JRE上时,会直接抛出UnsupportedClassVersionError,因为字节码版本不兼容。这也说明单独设置source无法保证代码能在指定版本JDK的编译输出下正常运行。
三、Maven推荐的release参数优势
release是JDK 9引入的参数,Maven编译插件(3.6.0及以上版本支持)使用它可以一次性解决语法校验、字节码版本、API限制三个核心问题:
- 等价于同时设置
--source和--target,还会自动引入对应版本的bootclasspath,强制代码只能调用指定Java版本的API - 例如配置
<release>8</release>时,示例1中调用String.isBlank()会直接在编译阶段报错,从根源避免运行时错误 - 配置更简洁,无需分别设置
source和target,也不用手动指定bootclasspath,减少配置出错的概率
内容的提问来源于stack exchange,提问作者morpheus
相关产品推荐
相关产品推荐

