Java 9 + Maven:如果两个依赖项导出同一个模块会怎样?
Java 9 + Maven: What happens if two dependencies export the same module?
我收到 java.lang.NoSuchMethodError
试图调用 Java 方法。据我所知,类路径在编译时和运行时是相同的,因此不应发生此错误。
重现步骤:
创建 4 个 Maven 项目:
- 我的图书馆
- ExtensionPresent
- 缺少扩展名
- 用户代码
模块 ExtensionPresent
和 ExtensionMissing
导出相同的模块名称。
ExtensionMissing
出口:
package dummy;
public class Extension {}
ExtensionPresent
出口:
package dummy;
public class Extension {
public static void present() {
System.out.println("Extension present!");
}
}
MyLibrary
将 ExtensionMissing
声明为依赖项。
UserCode
将 MyLibrary
声明为依赖项。
UserCode.main()
调用 Extension.present()
。这会触发编译时错误,因为 ExtensionMissing
不包含此方法。
- 现在是有趣的部分...在
UserCode
项目中,在 MyLibrary
之后添加 ExtensionPresent
作为依赖项。
- 我不再遇到编译器错误(该方法现在存在于编译时)。
- 当我尝试调用
UserCode.main()
时,我得到:
--- exec-maven-plugin:1.6.0:exec (default-cli) @ mavenproject3 ---
Exception in thread "main" java.lang.NoSuchMethodError: dummy.Extension.present()V
这是我的项目配置、Maven 实现或 JDK 工具中的错误吗?
(附带说明,我这样做是为了解决:Implementing a (compile-time) plugin architecture without split packages)
更新:这是一个可执行的测试用例:https://github.com/cowwoc/exec-maven-plugin-class-shadowing
当我启用调试日志记录时,我看到插件触发了以下命令:
compiler-maven-plugin
正在调用:javac -d ~/UserCode/target/classes -classpath ~/UserCode/target/classes: --module-path ~/.m2/repository/ExtensionPresent/1.0-SNAPSHOT/ExtensionPresent-1.0-SNAPSHOT.jar:~/.m2/repository/MyLibrary/1.0-SNAPSHOT/MyLibrary-1.0-SNAPSHOT.jar:~/.m2/repository/ExtensionMissing/1.0-SNAPSHOT/ExtensionMissing-1.0-SNAPSHOT.jar: -sourcepath ~/UserCode/src/main/java:~/UserCode/target/generated-sources/annotations: -s ~/UserCode/target/generated-sources/annotations -g -nowarn -target 9 -source 9 -encoding UTF-8
maven-exec-plugin
正在调用 java, --module-path, ~/UserCode/target/classes:~/.m2/repository/MyLibrary/1.0-SNAPSHOT/MyLibrary-1.0-SNAPSHOT.jar:~/.m2/repository/ExtensionMissing/1.0-SNAPSHOT/ExtensionMissing-1.0-SNAPSHOT.jar:~/.m2/repository/ExtensionPresent/1.0-SNAPSHOT/ExtensionPresent-1.0-SNAPSHOT.jar, -m, UserCode/com.usercode.Main]
这让我相信 maven-exec-plugin
以错误的顺序列出依赖项。我尝试手动调用应用程序,交换依赖项的顺序,果然程序运行了。
我针对 maven-exec-plugin 提出了 bug report。
我针对 maven-compiler-plugin 提出了第二个 bug report,因为它似乎也根据项目目录的名称将错误的顺序传递给 javac
(奇怪但真实)。
我收到 java.lang.NoSuchMethodError
试图调用 Java 方法。据我所知,类路径在编译时和运行时是相同的,因此不应发生此错误。
重现步骤:
创建 4 个 Maven 项目:
- 我的图书馆
- ExtensionPresent
- 缺少扩展名
- 用户代码
模块
ExtensionPresent
和ExtensionMissing
导出相同的模块名称。ExtensionMissing
出口:
package dummy;
public class Extension {}
ExtensionPresent
出口:
package dummy;
public class Extension {
public static void present() {
System.out.println("Extension present!");
}
}
MyLibrary
将ExtensionMissing
声明为依赖项。UserCode
将MyLibrary
声明为依赖项。UserCode.main()
调用Extension.present()
。这会触发编译时错误,因为ExtensionMissing
不包含此方法。- 现在是有趣的部分...在
UserCode
项目中,在MyLibrary
之后添加ExtensionPresent
作为依赖项。 - 我不再遇到编译器错误(该方法现在存在于编译时)。
- 当我尝试调用
UserCode.main()
时,我得到:
--- exec-maven-plugin:1.6.0:exec (default-cli) @ mavenproject3 ---
Exception in thread "main" java.lang.NoSuchMethodError: dummy.Extension.present()V
这是我的项目配置、Maven 实现或 JDK 工具中的错误吗?
(附带说明,我这样做是为了解决:Implementing a (compile-time) plugin architecture without split packages)
更新:这是一个可执行的测试用例:https://github.com/cowwoc/exec-maven-plugin-class-shadowing
当我启用调试日志记录时,我看到插件触发了以下命令:
compiler-maven-plugin
正在调用:javac -d ~/UserCode/target/classes -classpath ~/UserCode/target/classes: --module-path ~/.m2/repository/ExtensionPresent/1.0-SNAPSHOT/ExtensionPresent-1.0-SNAPSHOT.jar:~/.m2/repository/MyLibrary/1.0-SNAPSHOT/MyLibrary-1.0-SNAPSHOT.jar:~/.m2/repository/ExtensionMissing/1.0-SNAPSHOT/ExtensionMissing-1.0-SNAPSHOT.jar: -sourcepath ~/UserCode/src/main/java:~/UserCode/target/generated-sources/annotations: -s ~/UserCode/target/generated-sources/annotations -g -nowarn -target 9 -source 9 -encoding UTF-8
maven-exec-plugin
正在调用java, --module-path, ~/UserCode/target/classes:~/.m2/repository/MyLibrary/1.0-SNAPSHOT/MyLibrary-1.0-SNAPSHOT.jar:~/.m2/repository/ExtensionMissing/1.0-SNAPSHOT/ExtensionMissing-1.0-SNAPSHOT.jar:~/.m2/repository/ExtensionPresent/1.0-SNAPSHOT/ExtensionPresent-1.0-SNAPSHOT.jar, -m, UserCode/com.usercode.Main]
这让我相信 maven-exec-plugin
以错误的顺序列出依赖项。我尝试手动调用应用程序,交换依赖项的顺序,果然程序运行了。
我针对 maven-exec-plugin 提出了 bug report。
我针对 maven-compiler-plugin 提出了第二个 bug report,因为它似乎也根据项目目录的名称将错误的顺序传递给 javac
(奇怪但真实)。