Java8迁移至Java11遇包多模块访问及依赖类解析问题求解决方案
Java 8 迁移至 Java 11 常见问题解决方案
1. Package accessible from more than one modules(包可从多个模块访问)
问题原因
Java 9 引入的模块化系统(JPMS)禁止同一个包被多个模块导出,触发这个错误的常见场景:
- 项目依赖中存在重复包(两个不同的JAR包含了同路径的类)
- 模块路径和类路径混合使用,导致同一个包既来自模块化JAR又来自普通JAR
- 自定义模块的
module-info.java中同时依赖了两个导出相同包的模块
解决方案
- 排查并移除重复依赖:用构建工具的依赖树命令找到重复包,排除多余的依赖
- 清理模块配置:检查自定义模块的
module-info.java,避免同时依赖导出相同包的模块 - 优先使用模块化依赖:尽量升级依赖到支持JPMS的版本,减少类路径和模块路径的冲突
示例
Maven排查重复依赖
执行命令查看依赖树,定位重复包所在的依赖:
mvn dependency:tree -Dincludes=com.example:target-package
在pom.xml中排除多余的依赖:
<dependency> <groupId>com.example</groupId> <artifactId>problematic-library</artifactId> <version>1.0.0</version> <exclusions> <exclusion> <groupId>com.example</groupId> <artifactId>duplicate-package-lib</artifactId> </exclusion> </exclusions> </dependency>
修正模块配置
错误的module-info.java(同时依赖两个导出com.example.utils的模块):
module my.app { requires moduleA; requires moduleB; // moduleB也导出了com.example.utils }
修正后(只保留必要的依赖):
module my.app { requires moduleA; }
2. 依赖库中的类/变量无法解析
问题原因
- Java 11 移除了Java EE相关的内置模块(如
javax.xml.bind、javax.annotation) - 依赖库未适配JPMS,导致模块路径下无法访问类路径中的依赖
- 依赖的类被封装在模块中,但未通过
module-info.java导出
解决方案
- 补充缺失的JDK模块替代依赖:对于JDK移除的模块,手动引入第三方提供的替代包
- 调整模块声明:在
module-info.java中添加对依赖模块的requires声明;如果是自动模块(无module-info.java的JAR),使用其自动模块名 - 升级依赖版本:更换为支持Java 11/JPMS的依赖版本
示例
补充JDK移除的模块依赖
Java 11移除了javax.xml.bind,在pom.xml中添加第三方替代:
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.1</version> <scope>runtime</scope> </dependency>
声明自动模块依赖
比如旧版本Guava没有module-info.java,属于自动模块,在module-info.java中声明依赖:
module my.app { requires guava; // 自动模块名通常对应JAR的artifactId,如guava-28.0-jre.jar的模块名为guava }
编译时添加模块参数
如果编译时提示找不到类,可通过--add-modules参数手动添加模块:
javac --add-modules java.xml.bind -d target/classes src/main/java/com/example/*.java
内容的提问来源于stack exchange,提问作者Akhil Vasudevan
相关产品推荐
相关产品推荐

