前言
最近频繁遇到找不到类文件错误。
Caused by: java.lang.NoClassDefFoundError:xxx
就这个家伙。
但是我本地启动服务是正常的,前前后后经历了
惊讶 -> 疑惑 -> 烦躁 -> 暴躁 -> 心塞 -> 欣喜
在短短的小半天内,感觉心情像过了一个过山车+大摆锤,结束了,脑袋都是晕的。
关键是本地是正常的!
现在,请跟随我的视角,来看看这个让人心态差点爆炸的异常吧!
1遇到问题
在一顿噼里啪啦之后,代码写完,Junit 测试完毕、接口文档 Upload 到 YApi 完毕。果断发布 dev 环境!
直接进入启动重试!(PS:通过发布平台发布的)
这时候第一反应:本地启动一下试试!
- web started successfully
本地正常啊!
肯定是我启动姿势不正确,重新发布一下!
实锤了,和启动姿势没关系!
从淡定到暴躁
当然是看启动日志了。
PS: 服务没起来,只能 ssh 到服务器看日志。
- Caused by: java.lang.ClassNotFoundException:xxx
- Caused by: java.lang.NoClassDefFoundError:xxx
就这俩哥们,类找不到,奇了怪了。
这个类是通过三方 jar 包依赖进来的,我在 IDEA 里面 ? + B 还能进入源码!
这我不禁怀疑是不是因为开发环境使用的 Docker 容器的原因。
发布其他分支,是可以的。
莫非就是因为我引入了一个其他小伙伴提供的 jar,导致我现在用不了!
又是一顿调整依赖!
还不行!
难道是我引入的引来版本不对?
从其他项目找一找怎么用的!
依然不行!
难道是他的 jar 包里面又依赖了很多其他的?
试着 exclusion 掉其他依赖!
依然不行!
是我本地 jar 缓存?
删除本地磁盘上的 jar 试试?
解决方案就在灵光一闪
虽然 dev 用的是容器,咱拉不下来 jar 包。但是我可以本地打个包试试!
clean package
得到一个 jar 包
- jar -xvf xxx-web-1.0.0-SNAPSHOT.jar
进到 BOOT-INF/lib 里面
- % > ls | grep user
竟然啥也没有!
既然是打包没有打进去,那就看一下 mvn 依赖树的问题吧!
解决问题
项目结构
web 启动失败,是因为 service 添加的依赖,没有传递到 web,所以 web 打包没有打进去那个类。
注意,这里可以正常打包,本地环境可以正常启动。
奇怪吧!
现在进入解决方式:
- 查看 maven 依赖树
进入到 web module,执行以下命令。
- mvn dependency:tree>tree.txt
有这么一行错误:
- [WARNING] The POM for com.xxx:xxx-xxx-xxx:jar:1.0.1-SNAPSHOT is invalid, transitive dependencies (if any) will not be available, enable debug logging for more details
问题描述的很清晰,依赖传递失败,因为啥依赖传递失败呢?
再开启 debug 打印下错误:
- mvn -X dependency:tree>tree.txt
- [WARNING] The POM for com.xxx:xxx-xxx-xxx:jar:1.0.1-SNAPSHOT is invalid, transitive dependencies (if any) will not be available: 2 problems were encountered while building the effective model for com.xxx:xxx-xxx-xxx:jar:1.0.1-SNAPSHOT
- [ERROR] 'dependencies.dependency.version' for com.alibaba:easyexcel:jar is missing. @
- [ERROR] 'dependencies.dependency.version' for com.xxx:cache:jar is missing. @
说是因为下面两个 jar 的 version 找不到,所以会导致依赖传递失败。
PS: 我所有的依赖版本都是在父 POM 进行维护的,子 module 只有依赖 groupId 和 artifactId。
所以归根到底,是因为父 POM 的版本没有传递下去!
仔细一瞅,发现父 POM 的版本是 1.0.0,各个 module 的 parent 节点的属性也是
之前都是 SNAPSHOT 版本,后来因为公司的 nexus 配置了自动清除长时间不用的 SNAPSHOT 版本的依赖,我就去掉了 SNAPSHOT。
父 POM deploy 到私服的就是一个空的项目,里面就一个 POM 文件。
最后升级了一下父 POM 的版本,重新 deploy 一下,再改改各个 module 的依赖版本。
大功告成!
2总结
本文主要是含泪记下一个苦逼的问题排查过程。害,竟然没有第一时间想到原因!
下次再遇到记得 mvn -X dependency:tree>tree.txt 看下依赖树!
我的实践已经证明了:重启、清缓存、排除依赖都是没用的!
本文转载自微信公众号「程序员小航」,可以通过以下二维码关注。转载本文请联系程序员小航公众号。