ClassNotFoundException本质是JVM运行时类加载器在classpath中未找到目标类字节码,解决关键在于按类加载机制逐层排查:确认类是否真在运行时classpath、类名与包结构严格匹配、排除类加载器隔离及依赖未真正参与运行。

ClassNotFoundException 的本质不是“代码写错了”,而是 JVM 在运行时类加载器的搜索路径中,压根没找到目标类的字节码文件。解决它,关键在于理解类加载机制如何工作,并顺着这个链条逐层排查。
确认类是否真在运行时 classpath 中
编译通过 ≠ 运行时可用。JVM 只认启动时实际生效的 classpath:
- 命令行运行时,必须用 -cp 或 -classpath 显式包含所有 JAR 和 classes 目录,例如:
java -cp "lib/*:target/classes/" com.example.Main - Maven 打成普通 jar 后,默认不带依赖;要用 maven-shade-plugin 或 maven-assembly-plugin 构建 fat jar
- IDE(如 IntelliJ)里检查 Run Configuration → Classpath,确认模块输出目录和第三方库都已加入
- Spring Boot 项目注意 spring-boot-maven-plugin 是否执行了 repackage;否则
java -jar会因缺依赖而报错
核对类名与包结构是否严格一致
Java 类加载对大小写、符号、路径结构零容忍:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 代码写的是
com.example.UserService,但实际 class 文件在com/example/user/UserService.class→ 包名应为com.example.user,不匹配就找不到 - 加载内部类时,不能写
Outer.Inner,必须用Outer$Inner(JVM 字节码层面使用 $ 符号) - 拼写错误很隐蔽:比如
ArrayList写成Arraylist,HttpServlet写成Httpservlet
排查类加载器隔离与委托失效
在 Web 容器、OSGi 或自定义 ClassLoader 场景下,类存在≠能被当前加载器访问:
立即学习“Java免费学习笔记(深入)”;
- Tomcat 中,
WEB-INF/lib下的类由 WebAppClassLoader 加载,无法直接访问$CATALINA_HOME/lib下由 CommonClassLoader 加载的类 - 动态加载时慎用
Thread.currentThread().getContextClassLoader(),它可能不包含你要的类;优先尝试MyClass.class.getClassLoader() - 避免在静态块中用错误加载器去加载跨模块类,容易触发初始化失败
验证依赖是否真正参与运行时
尤其 Maven/Gradle 项目,ClassNotFoundException 常是依赖管理“看起来有、实际没”的结果:
- 执行
mvn dependency:tree -Dverbose,搜索目标类所在 artifact(如ObjectMapper属于jackson-databind),确认它未被excluded或因版本冲突被裁掉 - 检查
<scope>:设为provided的依赖(如 servlet-api)只在编译期有效,运行时需容器提供;本地测试或 Spring Boot 启动时会直接缺失 - 接口型依赖(如 slf4j-api)必须搭配具体实现(logback-classic 或 slf4j-simple),否则接口存在,实现类却找不到

















