You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

IntelliJ中Java 9非Jigsaw迁移的模块系统问题求助

Java 9 无模块(Jigsaw)迁移指南:多模块Maven项目适配

兄弟,我太懂你这种想以最小成本把Java 8多模块Maven项目迁去Java 9的心态了——毕竟没人没事想折腾Jigsaw那套模块系统对吧?先给你捋清楚不启用模块系统情况下的核心配置和常见坑,帮你搞定后续遇到的问题:

1. 统一父POM的Java版本配置

既然是多模块项目,父POMmyjava-service-parent是关键入口,要在这里统一设置Java 9相关编译参数,避免每个子模块重复配置:
在父POM的<properties>节点里添加:

<properties>
    <!-- 指定编译和目标版本为Java 9 -->
    <maven.compiler.source>9</maven.compiler.source>
    <maven.compiler.target>9</maven.compiler.target>
    <!-- 核心参数:强制Maven以非模块化模式编译,完全沿用Java 8的类路径逻辑 -->
    <maven.compiler.release>9</maven.compiler.release>
</properties>

另外注意:你的Maven版本必须升级到3.6.0及以上,旧版本对Java 9的兼容性极差,会出现各种莫名其妙的编译或打包问题。

2. 解决运行时的反射权限限制

Java 9的模块化系统默认会限制反射访问模块内的包,哪怕你自己的代码没启用模块,也会碰到依赖库(比如Spring、Hibernate这类大量用反射的框架)抛出IllegalAccessErrorNoClassDefFoundError的情况。
运行fat.jar时,需要添加--add-opens参数开放对应权限,举个通用例子:

java --add-opens java.base/java.lang=ALL-UNNAMED \
     --add-opens java.base/java.util=ALL-UNNAMED \
     --add-opens java.base/java.nio=ALL-UNNAMED \
     -jar myjava-service/target/myjava-service-fat.jar

解释ALL-UNNAMED代表你的非模块化代码所在的"未命名模块",--add-opens就是让指定的JDK模块包对它开放反射访问权限。遇到具体报错时,看日志里的包路径,对应添加参数即可。

3. 确保打包插件支持Java 9

你能正常mvn clean package说明编译没问题,但要是后续运行fat.jar出问题,得检查打包插件的版本:

  • 如果用maven-shade-plugin打包,必须升级到3.2.1及以上
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.4</version>
    <!-- 你的打包配置 -->
</plugin>
  • 如果是Spring Boot项目用spring-boot-maven-plugin,至少要升级到2.1.0及以上,旧版本打包的jar在Java 9下会有类加载异常。

4. 常见后续问题排查方向

你说编译打包正常但后续出问题,大概率逃不出这几个场景:

  • 依赖冲突:Java 9把原来JDK自带的一些API(比如JAXB、JAX-WS)做成了可选模块,原来Java 8里引入的第三方依赖可能和JDK自带版本冲突,用mvn dependency:tree分析依赖,排除冲突的JAR即可。
  • 废弃API替换:比如原来用sun.misc.BASE64Encoder这类私有API的代码,Java 9里已经被标记为废弃,要换成标准的java.util.Base64
  • 测试模块兼容性myjava-service-test里的测试框架(比如JUnit 4.x)可能需要升级版本,确保支持Java 9的类加载逻辑。

内容的提问来源于stack exchange,提问作者Eric Nascimento

火山引擎 最新活动