使用jdeprscan扫描Spring Boot项目时频繁出现“找不到类”错误的疑问
JDK8→JDK17 + Spring Boot 2→3升级:jdeprscan扫描问题解答
场景背景
我有一个基于JDK8和Spring Boot 2.6.8的Java REST API,计划升级至JDK17和Spring Boot 3.x。尝试用jdeprscan扫描项目JAR来定位需要更新的类:
jdeprscan target\myapplication.jar
最初使用Spring Boot Maven插件生成的JAR时,出现大量cannot find class错误,例如:
error: cannot find class org/slf4j/LoggerFactory
改用maven-assembly-plugin生成包含所有依赖的胖JAR后,扫描输出了不少有用的废弃类提示(比如org/apache/logging/log4j/util/LoaderUtil uses deprecated class ...),但仍存在部分找不到类的错误,例如error: cannot find class javax/servlet/FilterChain。
问题1:jdeprscan是否确实需要针对包含所有依赖类的JAR,而非spring-boot-maven-plugin生成的JAR?
- 是的,这是由两类JAR的结构差异和
jdeprscan的扫描逻辑决定的:- Spring Boot Maven插件生成的是可执行JAR,依赖包被嵌套在
BOOT-INF/lib目录下,并非直接合并到主JAR的类路径中。 jdeprscan仅会扫描指定JAR文件本身的类,不支持递归扫描JAR内部嵌套的其他依赖JAR,因此无法读取BOOT-INF/lib里的类,必然报找不到类的错误。maven-assembly-plugin生成的胖JAR将所有依赖类合并到同一个JAR文件中,jdeprscan可以直接遍历到所有类,从而输出有效的废弃类检测结果。
- Spring Boot Maven插件生成的是可执行JAR,依赖包被嵌套在
问题2:为何能通过java -jar正常运行的JAR,jdeprscan仍会提示“cannot find class ...”错误?
- 核心原因是运行时类加载机制和
jdeprscan的扫描机制完全不同:- 运行时:Spring Boot自带专属类加载器(
LaunchedURLClassLoader),会主动识别并加载BOOT-INF/lib下的所有依赖JAR,因此运行时能找到所有需要的类。 - 扫描时:
jdeprscan遵循标准JAR的类路径规则,没有Spring Boot的特殊类加载逻辑,既无法识别Spring Boot JAR的结构,也不会读取嵌套的依赖JAR。
- 运行时:Spring Boot自带专属类加载器(
- 即使是胖JAR仍出现找不到类的情况,可能的原因包括:
- 部分依赖是
providedscope(例如javax.servlet相关依赖,在Spring Boot中默认标记为provided,不会打包进胖JAR)。 - JDK17的模块化特性:原
javax.servlet包已被迁移至jakarta.servlet,jdeprscan在当前JDK类路径中找不到旧的javax.servlet类。 - 某些类是通过SPI、反射等方式动态加载的,未被打包进胖JAR。
- 部分依赖是
内容的提问来源于stack exchange,提问作者Woodchuck
相关产品推荐
相关产品推荐

