现象
运行期抛 java.lang.ClassNotFoundException: com.example.SomeClass;编译和单元测试通过,打包后启动或首次调用失败;随后出现 NoClassDefFoundError;仅容器镜像或应用服务器环境失败。
诊断
先确认类是否在部署产物里,再看运行时类路径与依赖树:
jar tf target/app.jar | grep 'com/example/SomeClass.class'
jcmd $(pgrep -f 'app.jar' | head -1) VM.system_properties | grep -i 'java.class.path'
mvn dependency:tree -Dincludes=com.example:some-lib
java -verbose:class -jar target/app.jar 2>&1 | grep SomeClass
jar tf 没有输出说明是打包问题,普通 jar 插件不会包含依赖;有输出但从未加载,则对比 java.class.path 与实际启动命令,并检查类加载器隔离。dependency:tree 中 scope 为 provided、test,或出现 omitted for duplicate,能直接指出缺失或被覆盖的版本。
根因
JVM 无法从调用方可见的类加载器中解析该类:类没被打包、被 shade 重定位、被 scope 排除,或由看不到应用 jar 的父加载器、插件加载器加载。
修复
把依赖 scope 改为 compile 或 runtime,用 fat jar 或显式 classpath 启动,并用 dependencyManagement 或 BOM 消除重复版本:
mvn -q dependency:tree -Dincludes=com.example:some-lib
mvn -q clean package
jar tf target/app.jar | grep 'com/example/SomeClass.class'
应用服务器场景按容器文档放置共享库,不要随意把 jar 丢进容器目录;也不要 catch 后吞掉异常或关闭校验。
验证
在没有 IDE classpath 的干净容器里运行打包产物,触发加载该类的代码路径,确认启动与请求都成功;依赖树中该库只有一个版本,生产镜像中同样通过。