Gradle打包Fat Jar时排除META-INF为何解决主类加载失败问题
为什么排除META-INF的SF/DSA/RSA文件能解决Fat Jar的主类加载失败问题?
我用Gradle构建Fat Jar时,最初的配置如下:
jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE manifest { attributes( 'Main-Class': 'com.kroger.cxp.app.Main' ) } from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } }
运行生成的Jar时,一直抛出could not find or load main Class错误。后来我添加了排除META-INF相关文件的配置,Jar就能正常运行了:
jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE manifest { attributes( 'Main-Class': 'com.kroger.cxp.app.Main' ) } from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }{ exclude "META-INF/*.SF" exclude "META-INF/*.DSA" exclude "META-INF/*.RSA" } }
这些META-INF文件是什么?
.SF:签名文件(Signature File),记录Jar内每个文件的哈希值,用于验证文件是否被篡改。.DSA/.RSA:签名证书文件,分别对应DSA和RSA加密算法,用来证明.SF文件的合法性,确保Jar包发布后未被修改。
这类文件是Java对Jar包做代码签名时生成的,很多第三方依赖Jar本身就是经过签名的。
为什么排除它们能解决主类加载失败?
构建Fat Jar时,会把所有依赖Jar的内容解压后合并到一个Jar里。这里的核心问题是签名验证冲突:
- 合并后的Fat Jar里,文件内容和原依赖Jar的签名文件记录的哈希值完全不符,Java类加载器会判定Jar包被篡改,拒绝加载任何类,包括你的主类。
- 即便你设置了
duplicatesStrategy = DuplicatesStrategy.EXCLUDE排除重复的签名文件,剩下的签名文件依然会验证整个Fat Jar的内容,而合并后的内容和原签名对应的Jar内容不一致,导致验证失败,类加载被阻断。
排除这些签名文件后,Java不会对Fat Jar执行签名验证逻辑,类加载器就能正常加载主类和所有依赖类,Jar也就可以正常运行了。
内容的提问来源于stack exchange,提问作者Aman Kumar Sinha
相关产品推荐
相关产品推荐

