mvn -v显示的Java版本不一定是编译所用JDK,真正决定编译行为的是pom.xml中maven-compiler-plugin的source/target配置、executable路径、toolchains.xml指定路径,以及javap -verbose输出的class文件major version。

只看 mvn -v 输出的 Java 版本,大概率不是 Maven 编译时真正用的 JDK。 它显示的是 Maven 进程启动时加载的 JVM 版本(即 JAVA_HOME 或系统默认 java),但编译行为可能被 pom.xml、toolchains 或 IDE 覆盖。必须分层验证。
查 pom.xml 里的 source/target 配置
这两个值不决定“用哪个 JDK”,但决定了生成 class 的字节码级别,是编译结果的底线约束:
-
<maven.compiler.source>17</maven.compiler.source>和<maven.compiler.target>17</maven.compiler.target>在<properties>中声明,属于项目级默认值 - 更优先的是
maven-compiler-plugin插件块里的<source>17</source>和<target>17</target>,它会覆盖properties - 如果插件里还配了
<executable>/path/to/javac</executable>,那连 JDK 都被硬指定,JAVA_HOME完全失效
运行 mvn -X compile 看真实调用的 javac
加 -X 是关键,否则日志不输出编译器路径和参数:
提供端到端的高端代理设置和使用指导,包括代理类型选择、地区定向、访问配置、API密钥验证和监控。
- Linux/macOS:
mvn -X compile 2>&1 | grep -i "javac" - Windows:
mvn -X compile | findstr /i "javac" - 关注输出中类似
[DEBUG] Command line options: -source 17 -target 17和[DEBUG] Using compiler 'javac'后面的完整路径,例如/usr/lib/jvm/java-17-openjdk-amd64/bin/javac - 若没看到路径,说明 Maven 正在用
JAVA_HOME下的bin/javac;若看到路径,那就是实际执行者
用 javap -verbose 确认 class 文件版本
这是唯一不可伪造的证据,绕过所有配置干扰:
立即学习“Java免费学习笔记(深入)”;
- 先执行
mvn clean compile - 挑一个生成的 class 文件,比如
target/classes/com/example/App.class - 运行:
javap -verbose target/classes/com/example/App.class | grep "major version" - 输出如
major version: 61→ 对应 Java 17;major version: 65→ Java 21;major version: 55→ Java 11 - 这个数字由实际编译器写入,和
java -version、IDE 设置、JAVA_HOME全部无关
别漏掉 toolchains.xml 这个隐藏开关
一旦项目启用了 maven-toolchains-plugin,pom.xml 和 JAVA_HOME 都可能被无视:
- 检查
pom.xml是否有maven-toolchains-plugin的<executions>配置 - 检查用户目录下
~/.m2/toolchains.xml是否存在,内容是否指定了<jdkHome>/usr/lib/jvm/java-21-openjdk-amd64</jdkHome></li> <li>如果存在且被启用,Maven 会强制使用该路径下的 JDK,无论其他配置怎么写</li> </ul> <p>最容易被忽略的是:Maven 启动用的 JDK(<code>mvn -v
显示的)、IDE 里设置的 Project SDK、pom.xml声明的source/target、以及toolchains指定的 JDK —— 这四者可以完全不同。只有javap -verbose输出的major version和mvn -X compile日志里的javac路径,才代表「此刻真正干活的那个 JDK」。

















