ClassNotFoundException 通常源于类名拼写错误或包路径错误,而非缺少 JAR;应优先检查大小写、空格、旧包名、反射字符串完整性,并结合 IDE 搜索、-verbose:class、jcmd、依赖范围及类加载器隔离等手段定位。

ClassNotFoundException 发生时,先确认是不是类名拼写或包路径错了
很多情况下 ClassNotFoundException 并不是缺 Jar,而是类名写错了——比如大小写不一致、多写了空格、用了旧包名(如 org.apache.commons.lang.StringUtils 写成 org.apache.commons.lang3.StringUtils),或者在反射中传了全限定名但漏了包前缀。
实操建议:
- 用 IDE 的「Go to Class」(Ctrl+Shift+N)搜索该类名,看能否定位到对应 class 文件;如果搜不到,说明当前 classpath 确实没这个类
- 检查异常堆栈里的
java.lang.ClassNotFoundException: xxx.xxx.XxxClass,把冒号后的完整类名复制出来,再反向查它属于哪个 Jar(例如去 Maven Repository 搜mvnrepository.com/search?q=xxx.xxx.XxxClass) - 如果是动态加载(
Class.forName("...")),确保字符串是运行时真正需要的类,而不是编译期就该存在的类
用 -verbose:class 或 jcmd 查看 JVM 实际加载了哪些类和 Jar
JVM 启动时加 -verbose:class 会打印每个被加载的类及其来源 Jar,虽然输出量大,但能直接看到目标类是否被尝试加载过、从哪加载的,比盲目猜更可靠。
实操建议:
- 启动命令加上
-verbose:class 2>&1 | grep "YourClassName",快速过滤关键行 - 程序已运行?用
jcmd不够,改用VM.native_memory summary jcmd(JDK 17+)或更通用的VM.class_hierarchy jstack配合jmap -clstats查类加载器层级 - 注意:
-verbose:class会显著拖慢启动,只在排查时临时启用,别留在生产配置里
检查 classpath 中是否真有提供该类的 Jar,尤其注意 scope 和依赖传递性
Maven 项目里,ClassNotFoundException 常见于 test scope 的依赖被主代码引用,或 provided 依赖在运行时未手动加入 classpath。Gradle 同理,compileOnly 和 runtimeOnly 容易埋坑。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
实操建议:
- Maven 下执行
mvn dependency:tree -Dincludes=group:artifact,确认目标类所属 Jar 是否出现在 compile/runtime 范围内 - 打包成 jar 后用
jar -tf your-app.jar | grep XxxClass,看类是否被打进去;如果没打进去,检查maven-shade-plugin或spring-boot-maven-plugin的配置有没有 exclude 错 - Tomcat/Jetty 等容器中,确认 Jar 是放在
WEB-INF/lib/下,而不是仅放在 IDE 的 Module Dependencies 里——后者只影响编译,不影响运行时 classpath
遇到 “类存在但报 ClassNotFoundException”,重点查类加载器隔离问题
不是所有 “找不到” 都是路径缺失。Web 应用、OSGi、模块化 JDK(--add-modules)、甚至 Spring Boot 的 LaunchedURLClassLoader,都可能造成同一个类被不同类加载器加载,导致 ClassCastException 或看似 ClassNotFoundException(实际是加载器 A 找不到加载器 B 加载的类)。
实操建议:
- 在抛异常处打断点,打印
YourClass.class.getClassLoader()和当前线程上下文类加载器Thread.currentThread().getContextClassLoader(),看是否一致 - Spring Boot 启动失败时,优先看
java.lang.NoClassDefFoundError是否由ExceptionInInitializerError引起——那往往说明静态块里触发了另一个ClassNotFoundException,得往深层挖 - Java 9+ 模块系统下,即使 Jar 在 classpath,若没在
module-info.java中requires对应模块,也会表现为找不到类
真正难的不是“怎么加 Jar”,而是判断“该由谁来提供这个类”——是框架自带、第三方 SDK、还是你自己的 module?一旦搞错归属,加再多 Jar 也白搭。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










