java项目中编译过程中的问题

jdk11的项目在执行打包的时候,在编译阶段报了以下的错误:

FlinkConfigAspect.java:0::0 Type java.lang.Throwable is indirectly referenced from required .class files but cannot be resolved since the declaring package java.lang exported from module java.base conflicts with a package accessible from module <unnamed>

由于我的项目是jdk11的版本,依赖的三方的jar中定义了moudle-info.java的模块配置信息,

Java 9 开始有了模块化系统的概念(JPMS), 每个Java 文件都属于某个模块. 例如上面例子中出现的 java.util.Throwable都属于JDK里面的 java.base 模块。

那么<unnamed> 模块是什么呢?

对于JDK本身, 它默认已经分了模块, 但是我们还有很多jar包, 并没有按照模块的方式去打包, 或者在JDK 9 之前就有了这些jar包, 我们照样可以依赖它们.

对各种模块的依赖, 会加到modulepath, 对于非模块的依赖, 继续使用classpath. classpath上的类会被统一的分配到一个叫<unnamed>的模块.

错误含义

所以, 这个错误的真正含义是: 在我们依赖中, java.lang包即出现在了 JDK 的 java.base 这个模块, 也出现在了我们依赖的classpath上. 而Java模块化系统不允许同一个包出现在2个模块里面。

排查结果:

经过排查最后发现引入的三方依赖中,自己定义java.lang包名:

总结:

即使第三方依赖没有定义 Throwable 类,只要它包含了 java.lang 包路径,就极有可能导致模块系统冲突。这是因为:

  1. 模块系统基于包名而不是特定类检测冲突

  2. java.lang 是 Java 平台保留的特殊包名

  3. 任何非 java.base 模块包含 java.lang 包都会导致包分裂问题

  • 模块系统冲突的核心机制是"包分裂"(Split Package)问题,而不是特定类的存在:
    • 包名冲突:模块系统不允许同一个包名出现在多个模块中
    • java.lang 的特殊性java.lang 是 Java 平台的核心包,由 java.base 模块独占
    • 自动模块命名:即使第三方依赖没有 module-info.java,当放在模块路径上时,它会被视为"自动模块"

解决方案的优先顺序应该是:

1.修复或替换问题依赖(最佳方案)

2.使用 Shade 插件重命名问题包

如果无法替换依赖,使用 Shade 插件重命名其中的非法包:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.4</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <relocations>
                    <relocation>
                        <pattern>java.lang</pattern>
                        <shadedPattern>shaded.javalang</shadedPattern>
                    </relocation>
                </relocations>
            </configuration>
        </execution>
    </executions>
</plugin>

3.确保问题依赖在类路径而非模块路径上

通过配置确保问题依赖在类路径上加载,而不是模块路径:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.11.0</version>
            <configuration>
                <compilerArgs>
                    <!-- 明确指定模块路径,确保问题依赖不在其中 -->
                    <arg>--module-path</arg>
                    <arg>${project.build.directory}/modules</arg>
                    <arg>--class-path</arg>
                    <arg>${project.build.directory}/classes:${project.build.directory}/dependency/*</arg>
                </compilerArgs>
            </configuration>
        </plugin>
    </plugins>
</build>

4.尝试使用模块系统参数

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.11.0</version>
    <configuration>
        <compilerArgs>
            <arg>--add-modules</arg>
            <arg>ALL-MODULE-PATH</arg>
            <arg>--add-opens</arg>
            <arg>java.base/java.lang=ALL-UNNAMED</arg>
            <!-- 尝试隐藏问题模块 -->
            <arg>--patch-module</arg>
            <arg>java.base=</arg>
        </compilerArgs>
    </configuration>
</plugin>

参考:

https://juejin.cn/post/7225629551601844282

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值