← 每日面试题 学习看板

程序运行期发生ClassNotFoundException 可能是什么原因?

面试题/01实践场景题/问题排查/程序运行期发生ClassNotFoundException 可能是什么原因?.md

面试记录 2026-10-14

题目:程序运行期发生 ClassNotFoundException 可能是什么原因?

难度:low

标签:practice/debug, java/classloading

评分:⭐⭐⭐☆☆(3/5)

我的回答

运行期间发生 class not found 一般是因为包的异常,引入包的异常,存在包冲突,某些包应该被其他引入了,但是没有被引入。

另外就是反射,反射使用获取了一个不存在的包,也可能会是 class not find。

再有就是一些动态加载的东西,这时候也可能会产生 class not find。

核心原因还是找不到,找不到对应的包,对应的类。

找不到的原因,可能是包冲突导致相互之间的冲突无法正常使用,可能是使用反射读取到错误的类名,都是有可能。根据具体的报警位置,然后去排查对应的问题。如果是包冲突,就对进,对行,进行相应调整。排除依赖或者引入新依赖,引入共享依赖。

明显是类名错误反射引起的,那么就对应的检查是何处传来了错误的类。对应的进行处理。

点评

优点:

不足:

补充:

完整讲解

第一部分:知识重点剖析

核心考点定位:考察对 JVM 类加载机制的深度理解——不只是"找不到类",而是"什么时候、在哪一层找不到"。

知识点拆解:

  1. CNFE vs NCDFE:ClassNotFoundException 是运行时抛出的 checked exception,代表首次加载失败;NoClassDefFoundError 是 Error,代表曾经加载成功但依赖的类缺失或静态初始化抛 ExceptionInInitializerError
  2. 类加载器委派模型:Bootstrap → Extension → Application → 自定义 ClassLoader。任何一层找不到都会向上问父加载器,父找不到再找子类。跨 ClassLoader 的类"互相看不见"是运行期 CNFE 的核心场景
  3. 运行期触发的三种路径:
  1. 常见根因:Maven provided 作用域依赖漏打、shade/uber-jar 过滤规则错误、多 ClassLoader 隔离(Tomcat/OSGi)、SPI 配置错、JDK 版本升级(javax. → jakarta.)
  2. 排查工具链:jcmd VM.classloader_dump、arthas sc -d、dependency:tree、-verbose:class、java -Xbootclasspath 检查扩展

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. CNFE 和 NCDFE 到底差在哪?给个具体例子。
  1. Spring Boot fat jar 的类加载器和 Tomcat 有本质区别吗?
  1. 线上运行期突然 CNFE,怎么快速定位是哪个 ClassLoader 出的问题?

第三部分:面试者参考回答(三步法口语化,300-400 字)

【一句话结论】

面试官您好,"运行期"这个关键词很重要——不是启动就报错,说明类路径没变,问题大概率来自"延迟加载触发"或"多 ClassLoader 隔离",我会先确认异常类型(CNFE 还是 NCDFE),再按 ClassLoader 层级排查。

【三点展开】

第一,先区分异常类型:ClassNotFoundException 是首次加载找不到 .class;NoClassDefFoundError 是曾经加载过但依赖缺失或静态初始化失败。后者更隐蔽,往往静态块里调用的类被 shade 过滤掉才会踩到。

第二,看调用栈定位触发路径:是反射 Class.forName 触发,还是 CGLIB 动态代理生成代理类失败,还是延迟执行的代码路径首次走。反射路径查传入的类名字符串对不对;动态代理查父类加载器和父类可见性。

第三,用 arthas sc -d <className> 看类的 ClassLoader 和 jar 路径,用 jcmd <pid> VM.classloader_dump 看每个 CL 的 URL 列表,确认类在哪个 ClassLoader 范围内。常见根因:Maven provided 依赖漏打、shade 过滤规则错误、Spring Boot 与 Tomcat 的 ClassLoader 差异、SPI 配置拼写错误。

【一句边界】

当然,如果是 JDK 9+ 模块系统,跨模块访问的类还会被 IllegalAccessError 拦截,那是另一个坑——运行期突然 CNFE 也可能只是模块名拼错触发的假象。