Ant + WebLogic 环境下的 JDK8 → JDK17 迁移调查
Ant + WebLogic 环境下的 JDK8 → JDK17 迁移调查
使用 jdeps / jdeprscan 进行依赖关系分析的实践记录
1. 整理调查对象
本次处理的是日本业务系统中常见的以下构成:
- Java EE 系统
- Ant 构建
- WebLogic Server 12c(对应 JDK8)
- Eclipse 开发环境
- 无依赖管理工具(不使用 Maven / Gradle)
注意: WebLogic Server 对 JDK17 的支持需要 14.1.1.0 → 14.1.2.0 以上版本。请确认现有的 WebLogic 版本,必要时请考虑升级。
本次工作是 JDK8 → JDK17 迁移的前期调查。
首先进行的是「确定扫描对象」的整理。
本系统以 EAR 格式进行分发,内部包含:
- WAR
- EJB jar
等多个模块。
因此,首先展开 EAR,将本次的调查对象整理为以下两类:
- classes 目录(已编译的 class 文件)
- 各种 jar 文件
也就是说,本次的任务是:
以从 EAR 分解得到的 class / jar 为对象,调查与 JDK17 的不兼容性。
2. jdeps 与 jdeprscan 的作用
在开始扫描之前,先整理一下两个工具的作用。
| 工具 | 目的 |
|---|---|
jdeps |
调查 jar / class 所依赖的类和模块 |
jdeprscan |
检测 Deprecated / Removed API 的使用位置 |
作业流程如下:
- 首先使用
jdeps掌握依赖关系,补全 classpath - 然后使用
jdeprscan检测 JDK17 不兼容的 API
3. 确定依赖关系(构建 classpath)
在使用 jdeps 或 jdeprscan 时,如果无法解析依赖的类,会出现以下错误:
class … not found
由于本项目不使用 Maven,因此不存在 pom.xml 或 dependency tree 这样的依赖管理。
在本项目中,最初的 classpath 设定仅使用了服务启动时 .bat 文件中所记载的内容(从日志中获取)。然而在扫描第一个 jar 文件时,便出现了上述错误。
原因在于,日志中记载的 classpath 仅包含 EAR 文件启动所需的依赖,而当前扫描对象是 jar 文件,因此需要的是 jar 文件构建时所使用的依赖。
为此,查阅了 Ant 的 build.xml,将 jar 构建时所使用的依赖补充到了 classpath 中。
即便如此,在后续扫描中该错误再次出现。借助 jdeps 的输出信息与 AI 辅助,找到了最后一块拼图——散布在各个 WAR 包中的 lib 目录。这说明,同一 EAR 包内的各模块之间存在依赖关系。
将各 WAR 的 lib 也加入 classpath 后,class not found 的错误得以彻底解决。
然而,另一个问题随之出现。
扫描结果中出现了「エラー: Methodref ……を解決できません」。
原因是 classpath 中存在同名但版本不同的 jar 包。由于 classpath 按从左到右的顺序进行类的检索,旧版 jar 被优先引用。而应用程序实际运行时使用的是新版 jar——新版相较旧版新增了方法的重载(オーバーロード)。因此,jdeprscan 参照旧版 jar 进行扫描时,该重载方法不存在,从而导致了解析失败。
Ant 项目的注意事项:
Ant 项目中不存在 Maven 的 dependency tree,因此还原 classpath 是最大的工作量。本次案例中,通过整合以下内容构建了可供扫描的 classpath:
- 启动脚本中的 classpath
- 项目内
lib目录- EAR 展开结果的 jar
- 各 WAR 内的
lib
实行命令示例:
set "cp=lib\*;modules\*;thirdparty\*"
set "JAR=扫描对象的绝对路径"
set "OUT=日志输出目标的绝对路径"
:: 依赖调查
"%JAVA_17_HOME%\bin\jdeps.exe" --class-path "%cp%" "%JAR%" > "%OUT%" 2>&1
4. API 扫描(jdeprscan)
classpath 构建完成后,执行 jdeprscan。
set "cp=lib\*;modules\*;thirdparty\*"
set "JAR=扫描对象的绝对路径"
set "OUT=日志输出目标的绝对路径"
:: 执行扫描(必须指定 --class-path 和 --release)
"%JAVA_17_HOME%\bin\jdeprscan.exe" --class-path "%cp%" --release 17 "%JAR%" > "%OUT%" 2>&1
注意:
省略--class-path选项,辛苦构建的 classpath 将完全不被使用,请务必明确指定。同时,明确指定
--release 17,可以从命令中一目了然地看出正在与 JDK17 的废弃 API 列表进行对照,也能防止在其他环境复用时发生误操作。
通过将日志输出到文件,可以在之后随时确认。
扫描结果示例
class com/example/app/LegacyUtil uses deprecated method java/lang/Thread::stop()V
class com/example/app/DataHelper uses deprecated method java/util/Date::<init>(III)V
class com/example/app/XmlParser uses deprecated class com/sun/org/apache/xml/internal/utils/URI
注意: 输出中包含
forRemoval=true的项目,是预计在未来版本中被删除的 API,请优先处理。
本次幸运的是,仅存在:
- 对旧 API 的引用
- 部分 deprecated API
因此不需要大规模的依赖更新或代码修改。
5. 应对大量代码修改
JDK 迁移还有另一个课题,那就是大量的代码修改。
确认 jdeprscan 的结果后,会在多处检测到 Deprecated API / Removed API。
由于手动修改这些内容非常耗时,目前正在开发一款使用 PowerShell v5.1 的辅助工具。
工具的使用流程如下:
- 解析扫描结果
- 提取修改候选
- 将 Evidence 输出到 CSV
- 人工审查
- 仅自动应用已批准的修改
也就是说,采用 AI + 自动化 + 人工审查 的形式。
关于该工具的详细内容,将在另一篇文章中介绍。
总结
对于 Ant + WebLogic 这样的遗留 Java EE 系统,JDK 迁移的第一道门槛就是掌握依赖关系。
本次调查采取了以下步骤:
- 展开 EAR,整理扫描对象
- 从启动脚本、
build.xml、EAR 展开结果、各 WAR 的lib构建 classpath - 使用
jdeps --class-path调查、补全依赖关系 - 使用
jdeprscan --class-path --release 17检测 API 不兼容性
对于不使用 Maven 的系统,正确构建 classpath 以及必须明确指定 --class-path 是非常重要的。
目前正在开发使用 PowerShell 的辅助工具,关于该工具也将在另一篇文章中介绍。
本文转载自作者的 Zenn 主页:https://zenn.dev/lockie2022
更多推荐



所有评论(0)