Spring Boot Uber-Fat Jar运行失败:主类找不到问题求助
排查Spring Boot Shaded Jar无法找到主类的问题
问题描述
为Spring Boot应用使用maven-shade-plugin构建Uber-Fat Jar,执行mvn clean install后生成普通Jar和Shaded Jar,普通Jar可正常运行,但运行Shaded Jar时抛出错误:
Error: Could not find or load main class com.walmart.SpringAppInitializer
pom.xml中插件配置如下:
<properties> <start-class>com.walmart.SpringAppInitializer</start-class> </properties> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <configuration> <fork>true</fork> <mainClass>${start-class}</mainClass> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>${start-class}</mainClass> </transformer> </transformers> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/maven/**</exclude> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <relocations> <relocation> <pattern>com.google.gson</pattern> <shadedPattern>com.shaded.google.gson</shadedPattern> </relocation> </relocations> <shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>shaded</shadedClassifierName> </configuration> </execution> </executions> </plugin> </plugins>
核心原因分析
- Spring Boot可执行Jar结构未被正确处理:Spring Boot的可执行Jar依赖特定的类加载器和资源结构,仅用
ManifestResourceTransformer无法满足需求,会导致主类无法被Spring Boot的启动逻辑加载。 - 插件执行顺序冲突:
spring-boot-maven-plugin的repackage目标会修改Jar结构,若maven-shade-plugin在其之后执行,会破坏Spring Boot的可执行结构。
解决方案
方案1:为Shade插件添加Spring Boot专属转换器
通过引入Spring Boot提供的资源转换器,确保Shaded Jar符合Spring Boot的可执行规范:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>${start-class}</mainClass> </transformer> <!-- 合并Spring Boot配置文件 --> <transformer implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer"/> <!-- 处理Spring Boot可执行Jar结构 --> <transformer implementation="org.springframework.boot.maven.SpringBootResourceTransformer"/> </transformers> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/maven/**</exclude> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <relocations> <relocation> <pattern>com.google.gson</pattern> <shadedPattern>com.shaded.google.gson</shadedPattern> </relocation> </relocations> <shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>shaded</shadedClassifierName> </configuration> </execution> </executions> <!-- 引入依赖确保转换器可用 --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> </dependency> </dependencies> </plugin>
方案2:调整插件执行顺序,让Spring Boot插件处理Shaded Jar
先让maven-shade-plugin生成Uber Jar,再让spring-boot-maven-plugin对其执行repackage:
- 修改Shade插件的执行阶段为
prepare-package:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <phase>prepare-package</phase> <goals> <goal>shade</goal> </goals> <configuration> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/maven/**</exclude> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <relocations> <relocation> <pattern>com.google.gson</pattern> <shadedPattern>com.shaded.google.gson</shadedPattern> </relocation> </relocations> <shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>shaded</shadedClassifierName> </configuration> </execution> </executions> </plugin>
- 修改Spring Boot插件,指定处理带
shaded分类器的Jar:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <configuration> <fork>true</fork> <mainClass>${start-class}</mainClass> <classifier>shaded</classifier> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin>
验证步骤
- 确认主类已被包含:
jar tf your-app-shaded.jar | grep com/walmart/SpringAppInitializer.class
- 查看Manifest配置是否正确:
jar xf your-app-shaded.jar META-INF/MANIFEST.MF cat META-INF/MANIFEST.MF
内容的提问来源于stack exchange,提问作者amit kumar
相关产品推荐
相关产品推荐

