在Java 9及之后的模块化系统中,module-info.java
文件引入了一种新的依赖管理机制,这与传统的类路径(classpath)管理方式不同。你遇到的问题通常是因为手动添加的第三方库没有模块化信息(没有自己的module-info.class
),这导致它们不能被模块系统识别。
原因分析
-
未模块化的第三方库:
- 大部分第三方库并没有更新以支持Java的模块系统,即它们没有自己的
module-info.java
文件。 - 这些库只能通过类路径(classpath)而不是模块路径(module path)被识别和使用。
- 大部分第三方库并没有更新以支持Java的模块系统,即它们没有自己的
-
模块路径 vs 类路径:
- 当你使用
module-info.java
文件时,Java编译器和运行时默认会使用模块路径来解析依赖。 - 没有模块化信息的第三方库无法通过模块路径解析,因此会导致导入失败。
- 当你使用
解决方法
有几种方法可以解决这个问题:
方法一:使用自动模块名称
如果你想保留module-info.java
文件,可以将未模块化的第三方库放在模块路径中,Java会为它们分配一个自动模块名称。你可以在module-info.java
中使用这个自动模块名称。
-
确定自动模块名称:
- 自动模块名称通常是JAR文件名去掉版本号和后缀,例如
mylib-1.0.jar
会被自动命名为mylib
.
- 自动模块名称通常是JAR文件名去掉版本号和后缀,例如
-
2. 在
module-info.java
中使用requires
语句:
module com.example.myapp {
requires java.logging;
requires mylib; // 自动模块名称
}
方法二:在类路径上使用第三方库
如果自动模块名称无法工作,或者你不确定自动模块名称,你可以将第三方库放在类路径上。
-
不使用模块系统:
- 通过删除
module-info.java
文件,所有库都会默认使用类路径方式,解决模块路径的问题。
- 通过删除
-
混合使用类路径和模块路径:
- 使用类路径和模块路径混合的方式。确保第三方库在类路径上,而你的代码在模块路径上。
-
2. 编译和运行命令:
-
编译时指定模块路径和类路径:
-
javac -p mods -cp libs/* -d out $(find . -name "*.java")
运行时指定模块路径和类路径:
-
java -p mods -cp libs/* -m com.example.myapp/com.example.myapp.Main
方法三:使用
jdeps
工具生成模块信息你可以使用
jdeps
工具生成简化的模块信息,创建一个模块化的JAR文件。 -
使用
jdeps
工具生成module-info.java
: -
jdeps --generate-module-info . path/to/your/library.jar
-
将生成的模块信息合并到你的项目中。