Maven多模块项目打包成单个可执行Jar遇执行失败问题求助
Maven多模块Uber Jar外部执行失败的排查与解决思路
一、先确认Jar的实际内容
把生成的a-1.0-SNAPSHOT.jar解压,重点检查这几点:
- 有没有
module b的class文件,路径是否和IDE里的一致(比如com/xxx/MainB.class) - 第三方依赖的class文件是否存在,要么在Jar根目录,要么在
lib子目录下 - 打开
META-INF/MANIFEST.MF,看Main-Class是否正确配置;如果是多启动类,确认插件有没有支持多入口的配置,另外Class-Path是否合理(Uber Jar一般不需要外置依赖,所以这里应该指向Jar内部的资源)
二、检查maven-assembly-plugin的配置细节
去module a的pom.xml里看插件配置:
- 确认
<descriptor>指定的assembly.xml里,有没有用<dependencySets>把module b和所有第三方依赖都包含进来 - 有没有开启
<includeModuleDependencies>true</includeModuleDependencies>,确保模块间依赖被打包进去 - 打包格式是不是
jar-with-dependencies,如果是自定义的descriptor,要核对所有需要打包的内容规则都没遗漏 - 检查
<executions>部分,有没有把插件绑定到package阶段,这样mvn install时才会触发Uber Jar的构建
三、排查依赖传递是否正常
在项目根目录跑mvn dependency:tree,看看module a是不是真的正确依赖了module b,有没有依赖缺失或者版本冲突的情况;另外确认module b的pom.xml里<packaging>是jar,并且mvn install后已经安装到本地Maven仓库了,不然module a找不到它。
四、根据错误日志定位问题
执行java -jar a-1.0-SNAPSHOT.jar时,把完整错误信息打出来(用java -jar a-1.0-SNAPSHOT.jar 2>&1):
- 如果是
ClassNotFoundException,直接找缺失的类是module b的还是第三方依赖的,回到Jar结构里看为啥没打包进去 - 如果是
NoClassDefFoundError,大概率是依赖冲突或者类加载顺序问题,去依赖树里找重复的依赖包,调整排除规则
五、换用maven-shade-plugin试试
如果assembly插件始终搞不定,换shade插件更靠谱,它处理Uber Jar的依赖合并更成熟,也支持多启动类:
在module a的pom.xml里加这段配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <!-- 设置默认启动类 --> <mainClass>com.example.MainA</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin>
跑mvn clean install后,要么直接用java -jar target/a-1.0-SNAPSHOT.jar启动MainA,要么用java -cp target/a-1.0-SNAPSHOT.jar com.example.MainB指定启动MainB。
内容的提问来源于stack exchange,提问作者FARS
相关产品推荐
相关产品推荐

