从一次ClassNotFoundException看大模型的技术分析可靠性
从一次ClassNotFoundException看大模型的技术分析可靠性
升级JDK 21 + Spring Boot 3.3.5时遇到springdoc报错,两个AI模型给出了截然相反的根因分析——一个说"类被移除了",一个说"类还没出生"。事实到底是什么?大模型为什么会在确定性的技术事实上翻车?
背景
在将项目从JDK 8 + Spring Boot 2.0升级到JDK 21 + Spring Boot 3.3.5的过程中,启动时遇到了如下报错:
java.lang.IllegalStateException: Error processing condition on
org.springdoc.webmvc.ui.SwaggerConfig.springWebProvider
Caused by: java.lang.NoClassDefFoundError:
org/springframework/web/servlet/resource/LiteWebJarsResourceResolver
Caused by: java.lang.ClassNotFoundException:
org.springframework.web.servlet.resource.LiteWebJarsResourceResolver
环境信息:
- JDK 21
- Spring Boot 3.3.5
- springdoc-openapi-starter-webmvc-ui 2.6.0
两次AI分析,两个截然相反的结论
通义灵码的分析
这个错误是因为Spring Boot 3.x已经移除了
LiteWebJarsResourceResolver类。这个类在Spring Boot 2.x中用于处理WebJars资源,但在Spring Boot 3.x中已被移除。
给出的解决方案是:移除webjars相关配置、修改拦截器、添加spring.web.resources.add-mappings=true。
按提示操作后,报错依然存在。
扣子的分析
LiteWebJarsResourceResolver不是被移除了,而是Spring Framework 6.2才新增的类,Spring Boot 3.3.5对应的Spring Framework 6.1.14没有这个类。问题根源还是springdoc版本。
给出的排查步骤:
mvn dependency:tree -Dincludes=org.springdoc确认实际解析版本- 清理本地Maven缓存后重新编译
- 如果确认是2.6.0仍报错,降到2.5.0
将springdoc降到2.5.0后,问题解决。
事实到底是什么?
查Spring Framework的源码和Javadoc,时间线很清晰:
| 版本 | 是否包含LiteWebJarsResourceResolver |
|---|---|
| Spring Framework 5.x(对应Boot 2.x) | ❌ 不存在 |
| Spring Framework 6.1.x(对应Boot 3.3.x) | ❌ 不存在 |
| Spring Framework 6.2.x(对应Boot 3.4.x+) | ✅ 新增 |
所以扣子是对的,通义灵码是错的。
LiteWebJarsResourceResolver从来就不存在于Spring Boot 2.x时代,它是Spring Framework 6.2才新增的类。springdoc 2.6.0开始引用了这个新类,但Spring Boot 3.3.x的Spring Framework版本还停留在6.1.x,所以出现了ClassNotFoundException。
通义灵码说的"2.x有、3.x移除了"完全是无中生有。
大模型为什么会翻车?
Spring的版本变更记录是公开的、确定的事实,哪个版本有哪个类应该是清晰可查的。那为什么模型还会搞错?
1. 模型不是查文档,是在"回忆"训练数据
模型没有实时查API文档的能力,它靠训练时见过的信息来"推断"。对于讨论充分的API变更(比如javax→jakarta的包名迁移),训练数据里大量讨论,模型能答对。但LiteWebJarsResourceResolver是一个非常冷门的类,网上几乎没人讨论过,模型没见过相关信息,只能靠推理。
2. 遇到不确定时,模型会"合理推测"而不是承认不知道
通义灵码看到报错链路是SwaggerConfig → LiteWebJarsResourceResolver → ClassNotFoundException,又知道从Boot 2.x升到3.x,就直接推理出"2.x有3.x移除了"——听起来合理,但事实恰好相反。
正确的分析——“这个类是6.2新增的,你的Boot版本对应的Framework不够新”——需要一个非常具体的知识点。而错误的分析——“3.x移除了2.x的类”——符合"升级后找不到类"的一般直觉,模型倾向于选择这种"能解释现象"的答案。
3. 模型倾向于给出"有解释力的答案"而非"正确的答案"
两个答案都能解释"为什么找不到类",但方向完全相反。模型在缺乏确切知识时,会优先选择逻辑上"自洽"的解释,而不是停下来承认"我不确定"。
正确的排查方式
遇到框架类的ClassNotFoundException,直接查证比问模型靠谱得多:
# 查看实际解析的依赖版本
mvn dependency:tree -Dincludes=org.springdoc
# 直接搜本地仓库中是否存在目标类
find ~/.m2/repository/org/springframework -name "LiteWebJarsResourceResolver.class"
或者直接查Spring官方Javadoc,搜索类名,看@since标注:
LiteWebJarsResourceResolver— @since 6.2
一行注释,胜过千言万语。
最终解决方案
将springdoc-openapi版本从2.6.0降到2.5.0:
<springdoc.version>2.5.0</springdoc.version>
2.5.0不依赖Spring Framework 6.2的类,与Spring Boot 3.3.x完美兼容。
反思
这件事给我一个深刻教训:大模型对冷门API变更的事实判断不可靠,越是"解释得通"的结论越要警惕。
大模型擅长的是代码生成、逻辑推理、方案设计这些需要"综合能力"的场景。但在"某个类的引入版本号是多少"这种确定性事实面前,它本质上是在猜——猜对了是你运气好,猜错了你就要踩坑。
下次遇到类似问题,先查官方文档和源码,再让模型帮你分析。模型是工具,不是百科全书。
更多推荐




所有评论(0)