Spring Boot签名Jar后无法读取组件,REST接口返回404
Hey there, I’ve run into this exact issue before—signed a working Spring Boot executable Jar, suddenly all endpoints return 404 even though embedded Tomcat boots up without errors. The root cause you found (AppClassLoader can’t load your package classes) is spot-on, so let’s break down why this happens and how to fix it:
Core Issue Breakdown
When you sign a Jar, if the process messes up the Jar structure, manifest config, or class permissions, Spring Boot can’t scan and initialize your controllers/services. Tomcat starts fine because the core Spring Boot/Tomcat classes load without issue—but your application beans are never registered, hence the 404s.
Common Causes & Fixes
Signature process corrupted Jar structure
Some signing tools or custom scripts accidentally modify class paths or overwrite critical Jar metadata.- First, verify the Jar’s contents before and after signing with
jar tf your-app.jar—check that your business package (e.g.,com/yourcompany/yourapp/controller) is intact and matches the unsigned version. - Use the official Spring Boot build + signing workflow:
- Build the executable Jar normally with
./mvnw package(Maven) or./gradlew bootJar(Gradle). - Sign it with
jarsigner(avoid random third-party tools):
Skip any extra flags that might alter the Jar’s internal structure.jarsigner -keystore your-keystore.jks your-app.jar your-alias
- Build the executable Jar normally with
- First, verify the Jar’s contents before and after signing with
Classloader permission restrictions
Signed Jars run in a trusted security context, but if your package isn’t properly authorized, AppClassLoader might block class loading.- Check the
MANIFEST.MFin the signed Jar—addPermissions: all-permissionsif your app needs full access (adjust based on your security requirements). - If needed, use a security policy file to grant access to your Jar:
- Create
app-policy.policy:grant codeBase "file:./your-app.jar" { permission java.security.AllPermission; }; - Start the Jar with:
java -Djava.security.policy=app-policy.policy -jar your-app.jar
- Create
- Check the
Broken Spring component scanning
Signing can sometimes interfere with Spring’s auto-scanning logic, even if your@SpringBootApplicationannotation was working before.- Explicitly define your scan base packages in the main application class to leave no room for ambiguity:
@SpringBootApplication(scanBasePackages = "com.yourcompany.yourapp") public class YourApp { public static void main(String[] args) { SpringApplication.run(YourApp.class, args); } } - Add the
-Ddebugflag when starting the Jar to see Spring’s component scan logs—you’ll immediately spot if your controllers aren’t being picked up.
- Explicitly define your scan base packages in the main application class to leave no room for ambiguity:
Java version mismatch between build and signing
If you built the Jar with Java 11 but signed it with Java 17 (or vice versa), class file version incompatibilities can block loading.- Verify versions with
java -versionandjarsigner -version—they should match. - Rebuild and re-sign using the same Java runtime.
- Verify versions with
Quick Debugging Trick
Add this snippet to your main class to confirm class loading behavior before Spring starts:
public static void main(String[] args) { try { Class<?> testController = Class.forName("com.yourcompany.yourapp.controller.HomeController"); System.out.println("Successfully loaded class with loader: " + testController.getClassLoader()); } catch (ClassNotFoundException e) { e.printStackTrace(); System.out.println("Context classloader: " + Thread.currentThread().getContextClassLoader()); } SpringApplication.run(YourApp.class, args); }
This will tell you exactly if the class is missing, and which loader is trying to find it.
内容的提问来源于stack exchange,提问作者Jairton Junior

