TL;DR When building a fat JAR, signature files from individual JARs cannot be verified against the merged JAR, causing a SecurityException. Exclude signature files under META-INF using the maven-shade-plugin to resolve the issue.
The Problem
Recently I encountered an error when trying to run a fat jar:
Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:287) at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:240) at java.util.jar.JarVerifier.processEntry(JarVerifier.java:317) at java.util.jar.JarVerifier.update(JarVerifier.java:228) at java.util.jar.JarFile.initializeVerifier(JarFile.java:348) at java.util.jar.JarFile.getInputStream(JarFile.java:415) at sun.misc.URLClassPath$JarLoader$2.getInputStream(URLClassPath.java:775) at sun.misc.Resource.cachedInputStream(Resource.java:77) at sun.misc.Resource.getByteBuffer(Resource.java:160) at java.net.URLClassLoader.defineClass(URLClassLoader.java:436) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:425) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:358) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)
Some jar packages contain a .SF file in META-INF, which includes the hashes of the class files and resource files in the original jar package, used for verifying file integrity and other validations.
The Problem Caused by Maven Shade
However, when building a fat jar, we combine many jar packages into one. This means the fat jar ends up containing signature files from each individual jar, but they obviously cannot be validated against the final fat jar.
Solution
The solution is to remove all signature files during packaging. If you’re using Maven, you can use the shade plugin: