PAYATHON 2026

Java 17 迁移后 ADF 在 WebLogic 14.1.2 中出现模块包冲突

数据小许

这类错误表明 Java 模块系统(JPMS)发现了包来源冲突:某个模块同时读取了两个包含同名包的模块。删除重复版本的 JAR 不一定能解决问题,因为两个不同的 JAR 即使没有重复类,也可能包含同一个包。

应先确认 JDeveloper 是否将 ADF 和其他传统依赖放到了 module-path,再核对 ADF 库的来源和版本。仅凭现有信息,还无法确定应该删除哪个 ADF JAR,也无法确认当前 ADF、JDeveloper、WebLogic 与 JDK 的具体组合是否受支持。

如何理解这些报错

以这条错误为例:

module commons.validator reads package oracle.adf.share.security.policystore from both adf.share.support and adf.share.security

在当前解析出的模块关系中,commons.validator 同时读取了 adf.share.support 和 adf.share.security,而后两个模块都提供了 oracle.adf.share.security.policystore 包。

报错中出现 commons.validator,并不意味着需要修改 Commons Validator。应检查提供冲突包的两个模块,以及它们为什么进入了同一个模块图。

另外两条错误分别涉及:

  • javax.naming:外部 jndi 模块与 JDK 的 java.naming 模块冲突。
  • org.w3c.dom:外部 xalan 模块与 JDK 的 java.xml 模块冲突。

包冲突与同一个库加载了两个版本并不完全相同。即使每个依赖都只有一个版本,不同库之间仍可能包含同名包。

先确定错误发生在哪个阶段

从日志中确认错误发生在 JDeveloper 的编辑器检查、编译、部署,还是 WebLogic 启动应用时。然后查看对应阶段的实际参数,重点查找:

--module-path
-p
--class-path
-classpath
-cp
--add-modules

同时检查项目是否存在 module-info.java,以及 JDeveloper 的项目依赖、编译器选项和运行配置中是否启用了模块相关设置。具体界面位置取决于 JDeveloper 版本,应以实际生成的参数为准。

即使应用没有 module-info.java,放在 module-path 上的普通 JAR 也可能被识别为 automatic module。因此,清理 classpath 后仍然报错,不能证明 module-path 已经没有冲突。

找到模块对应的实际 JAR

使用 Java 17 的 jar 工具检查候选文件。以下路径是占位示例,需要替换成项目实际使用的文件:

jar --describe-module --file /path/to/library.jar
jar --list --file /path/to/library.jar

第一条命令用于查看模块描述或派生的 automatic module 信息;第二条用于查看 JAR 内容。能够派生出模块名称,不代表该 JAR 在当前构建中一定通过 module-path 加载,仍需结合构建参数判断。

针对 ADF 错误,分别检查两个候选 JAR 是否包含以下目录下的类:

oracle/adf/share/security/policystore/

其他错误也应按完整包名逐项检查。不同子包是不同的包,不能仅凭两个 JAR 都含有 oracle/adf/share/ 目录就判定它们冲突。

记录每个冲突 JAR 的完整路径,特别留意它是否来自:

  • JDeveloper 或 ADF 安装目录中的库定义。
  • 项目手工维护的依赖目录。
  • 已导入的其他项目或共享库。
  • EAR、WAR 或部署配置额外引入的依赖。

删除项目目录中的一个文件后,IDE 库定义或其他路径仍可能引用另一份文件。

根据应用是否需要 JPMS 调整配置

如果应用继续采用传统 classpath 构建和部署,且工具链支持这种方式,可以将误放到 module-path 上的传统依赖恢复到 classpath。对于同名包分布在多个 JAR 中的旧库,应优先检查这方面的配置。

下面仅演示两类参数的区别,不是完整的 ADF 构建命令:

# 通过 module-path 解析依赖
javac --module-path "lib" ...

# 通过传统 classpath 查找依赖
javac -classpath "lib/*" ...

classpath 不施加相同的 JPMS 包解析约束,但重复类仍可能造成类加载顺序问题,因此仍需清理实际重复的依赖。

如果应用必须作为命名模块构建,就需要从依赖组合上消除冲突,例如采用不再拆分同名包的兼容库组合。仅修改 requires 或模块名称,不能消除两个被读取模块都包含同一个包的问题。

核对 ADF 库的版本与部署来源

如果 ADF 内部包仍然冲突,应重点检查是否混用了不同安装目录、不同发布版本或不同补丁级别的库。

建议按以下顺序处理:

  1. 记录实际使用的 JDeveloper、ADF Runtime、WebLogic 和 JDK 的完整版本及补丁信息。
  2. 核对该组合的官方认证信息和部署要求。WebLogic 的 JDK 支持情况不能单独证明整套 ADF 开发及运行环境兼容。
  3. 根据对应版本的 ADF 库定义和部署要求,整理项目依赖,清除旧环境残留的手工引用。
  4. 检查 EAR/WAR 中的内容,确认需要由服务器或共享库提供的依赖是否又被应用重复打包。具体保留位置应遵循所用版本的部署要求。
  5. 修正依赖配置后,清理构建输出和缓存,再重新构建。

不要仅凭模块名称就删除 adf.share.support 或 adf.share.security 对应的文件。它们可能各自包含应用需要的类;删除其中一个可能消除当前错误,却会引入后续的缺类问题。

哪些做法不能直接解决问题

--add-reads、--add-exports 和 --add-opens 分别用于调整可读性、导出或反射访问,不能直接消除这里的同名包冲突。

如果错误发生在编译阶段,调整 WebLogic 的应用类加载优先级也无法修复编译器的模块解析错误。应先解决产生错误的那个阶段,再检查部署后的类加载情况。

下一步应取得首次报错阶段的完整参数,以及两个冲突 ADF 模块对应的 JAR 完整路径。这些信息有助于区分问题是出在 module-path 配置、ADF 库混用,还是依赖本身不适合当前的模块化构建方式。

备注:内容仅供参考。