我的java程序被打包在一个jar文件中,并使用了一个外部jar库,bouncy castle。我的代码编译良好,但运行jar会导致以下错误:
java.lang.SecurityException: Manifest主属性的签名文件摘要无效
我在谷歌上搜索了一个多小时,想要找到一个解释,但几乎没有什么价值。如果有人看到这个错误之前,可以提供一些帮助,我将不胜感激。
我的java程序被打包在一个jar文件中,并使用了一个外部jar库,bouncy castle。我的代码编译良好,但运行jar会导致以下错误:
java.lang.SecurityException: Manifest主属性的签名文件摘要无效
我在谷歌上搜索了一个多小时,想要找到一个解释,但几乎没有什么价值。如果有人看到这个错误之前,可以提供一些帮助,我将不胜感激。
当前回答
我在使用IntelliJ IDEA 14.01时遇到了这个问题。
我可以通过以下方法修复它:
文件->项目结构->添加新的(工件)->jar->从模块与依赖创建jar从模块窗口:
选择你的主要类
来自库的JAR文件 选择复制到输出目录和链接通过清单
其他回答
Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:314) at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:268) at java.util.jar.JarVerifier.processEntry(JarVerifier.java:316) at java.util.jar.JarVerifier.update(JarVerifier.java:228) at java.util.jar.JarFile.initializeVerifier(JarFile.java:383) at java.util.jar.JarFile.getInputStream(JarFile.java:450) at sun.misc.URLClassPath$JarLoader$2.getInputStream(URLClassPath.java:977) at sun.misc.Resource.cachedInputStream(Resource.java:77) at sun.misc.Resource.getByteBuffer(Resource.java:160) at java.net.URLClassLoader.defineClass(URLClassLoader.java:454) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
帮助我的(IntelliJ IDEA 2016.3): 文件->项目结构-> Artifacts ->添加JAR ->选择主类->选择“通过manifest复制到输出目录和链接”->确定->应用->构建->构建Artifacts…- >构建
假设您使用ant构建jar文件,您可以指示ant去掉META-INF目录。这是我的蚂蚁目标的简化版本:
<jar destfile="app.jar" basedir="${classes.dir}">
<zipfileset excludes="META-INF/**/*" src="${lib.dir}/bcprov-jdk16-145.jar"></zipfileset>
<manifest>
<attribute name="Main-Class" value="app.Main"/>
</manifest>
</jar>
您可以使用Shadow生成一个jar。
Shadow是一个Gradle插件,用于将项目的依赖类和资源组合到一个输出Jar中。组合罐通常被称为fat-jar或super - Jar。
Modify build.gradle plugins { ... // ① Add the shadow plugin id "com.github.johnrengelman.shadow" version "5.2.0" } ... // ② Config the shadow jar, its name is baseName-1.0-classifier.jar shadowJar { archiveBaseName.set('baseName') archiveClassifier.set('classifier') archiveVersion.set('1.0') manifest { attributes 'Main-Class': 'Main' } } // ③ Disable the default jar task jar.enabled = false // ④ Execute the shadowJar task when compiling build.dependsOn(shadowJar) Execute the command gradle build, the jar file will be generated: <Project Directory>/build/libs/baseName-1.0-classifier.jar
有些依赖项可能是带符号的jarfile。当您将它们全部组合到一个大的jarfile中时,相应的签名文件仍然存在,并且不再与“大的组合”jarfile匹配,因此运行时停止认为jar文件已被篡改(它…可以这么说)。
假设您正在使用ant,可以通过从jarfile依赖项中删除签名文件来解决这个问题。不幸的是,在ant中不可能一步到位。
但是,我能够在Ant中分两步实现这个功能,而不需要具体地命名每个jarfile依赖项,通过使用:
<target name="jar" depends="compile" description="Create one big jarfile.">
<jar jarfile="${output.dir}/deps.jar">
<zipgroupfileset dir="jars">
<include name="**/*.jar" />
</zipgroupfileset>
</jar>
<sleep seconds="1" />
<jar jarfile="${output.dir}/myjar.jar" basedir="${classes.dir}">
<zipfileset src="${output.dir}/deps.jar" excludes="META-INF/*.SF" />
<manifest>
<attribute name="Main-Class" value="com.mycompany.MyMain" />
</manifest>
</jar>
</target>
sleep元素的作用是防止将来出现关于修改日期的文件的错误。
我在链接线程中发现的其他变化并不适合我。
对于那些使用gradle并试图创建和使用fat jar的人来说,下面的语法可能会有所帮助。
jar {
doFirst {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}