含外部依赖的Jar文件首次运行正常 后续触发ClassNotFound异常
问题排查与解决方案
核心问题原因
- 你当前的打包、类路径配置存在多处路径不匹配、依赖加载逻辑错误,是导致首次运行正常、后续抛
ClassNotFound异常的根因:- JVM默认的类加载器不支持加载嵌套在Jar包内部的Jar文件,你把
connector.jar、activation.jar、javax.mail.jar直接打进CM.jar的操作是无效的,就算反编译能看到这些Jar存在,类加载器也找不到里面的类。 - 首次运行能成功,是因为你测试时的当前工作目录下刚好存在独立的
lib文件夹,里面放了三个依赖Jar,Manifest里配置的Class-Path相对路径此时能生效;10-15秒后失效,大概率是你移动了CM.jar的位置、或者删除/修改了当前目录下的lib文件夹,导致依赖路径失效。 - 你的编译、打包、Manifest配置的依赖路径完全不匹配:编译命令里的
connector.jar配了绝对路径/lib/connector.jar,打包时又把邮件依赖放到了EmailHelper/lib/路径下,Manifest里却写的是lib/下的路径,路径不一致自然会出现偶发的类找不到问题。
- JVM默认的类加载器不支持加载嵌套在Jar包内部的Jar文件,你把
修复方案
方案1:使用外部依赖目录运行(配置简单,适合本地测试)
- 保持CM.jar运行目录的同级存在独立的
lib文件夹,里面放入三个依赖文件,文件名要和Manifest里写的完全一致:connector.jar、activation.jar、mail.jar(如果你Manifest里写的是mail.jar就不要用javax.mail.jar的文件名)。 - 修正Manifest文件:确保
Class-Path的每一项路径、文件名和实际文件完全匹配,Manifest每行末尾不要留多余空格,最后一行必须保留空行。 - 重新打包,打包命令只需要传入你自己编译生成的
.class文件,不要再把依赖Jar包打进CM.jar里,无效还会干扰路径识别。
方案2:打可执行Fat Jar(无外部依赖,适合分发)
- 先将三个依赖Jar分别解压,提取出里面所有的
.class文件和资源文件。 - 把你自己编译生成的
.class文件,和依赖解压出来的文件放在同一个根目录下(注意不要覆盖自定义的MANIFEST.MF文件)。 - 用jar命令打包所有文件即可,打出来的CM.jar可以单独运行,不需要额外的lib目录。
排查辅助技巧
运行Jar时加上-verbose:class参数,可以输出所有类的加载路径,能直接定位到缺失的类是在哪个路径下加载失败的,方便快速确认路径配置问题。
内容的提问来源于stack exchange,提问作者Wesley Stewart
相关产品推荐
相关产品推荐

