Key Takeaways
You've built a Spring Boot application. Running it from the command line is straightforward — just type `java -jar myapp.jar` and watch it start. But what happens when you need to launch that same application from inside another Java program? What if you're building a test framework that spins up Spring Boot apps dynamically, or a CI/CD pipeline that needs to orchestrate multiple microservices?
That's where things get interesting. Programmatic launch isn't the default use case, so Spring Boot doesn't advertise it prominently. But the capability exists, and once you understand how the Spring Boot Loader works, you can unlock powerful patterns for testing, orchestration, and automation.
At Boundev, we've helped dozens of teams implement programmatic launch patterns for their Java applications. In this guide, we'll walk through exactly how it works, complete with working code examples, use cases, and the pitfalls to avoid.
Why Launch Spring Boot Programmatically?
Before diving into the "how," let's address the "why." Running `java -jar` works perfectly for most scenarios. So why would you need to launch a Spring Boot application from within another Java program?
The truth is, this requirement surfaces in specific but important scenarios:
Common Use Cases for Programmatic Launch
If any of these scenarios resonate with your use case, keep reading. The programmatic launch approach we'll show you handles exactly these situations.
Need Java developers who understand Spring Boot internals?
Boundev's pre-vetted Java developers have deep experience with Spring Boot architecture, including programmatic launch patterns and advanced deployment scenarios.
See How We Do ItUnderstanding How Spring Boot Launches
To launch Spring Boot programmatically, you first need to understand how it normally launches. When you run `java -jar myapp.jar`, the Java runtime doesn't just execute your code. Instead, it loads special classes from the Spring Boot Loader JAR and uses them to bootstrap the application.
Spring Boot packages your application as an "executable JAR" that includes a nested loader JAR. This nested structure is what enables the `java -jar` approach — but it also means you can't simply call `main()` directly. The startup process involves:
Java loads the Spring Boot Loader classes from the nested JAR
JarFileArchive reads the JAR structure and its entries
JarLauncher creates an archive and determines the main class
LaunchMethod.invoke() calls your application's main() method
For programmatic launch, you'll replicate these steps using Java reflection. The key classes you need are inside the `org.springframework.boot.loader` package, and you'll load them dynamically from the JAR file.
The Complete Code: Launching Spring Boot Programmatically
Here's the full implementation. We'll break it down step by step after showing you the complete method.
public class SpringBootLauncher {
public static void launch(String jarPath, String[] args) throws Exception {
File jarFile = new File(jarPath);
URL jarUrl = jarFile.toURI().toURL();
URLClassLoader classLoader = new URLClassLoader(
new URL[]{jarUrl},
SpringBootLauncher.class.getClassLoader()
);
// Step 1: Create JarFileArchive
Class> archiveClass = classLoader.loadClass("org.springframework.boot.loader.jar.JarFileArchive");
Constructor> archiveConstructor = archiveClass.getDeclaredConstructor(File.class);
archiveConstructor.setAccessible(true);
Object archive = archiveConstructor.newInstance(jarFile);
// Step 2: Get the main class name
Class> launcherClass = classLoader.loadClass("org.springframework.boot.loader.Launcher");
Method getMainClassMethod = archiveClass.getDeclaredMethod("getMainClass");
String mainClassName = (String) getMainClassMethod.invoke(archive);
// Step 3: Create JarLauncher instance
Constructor> jarLauncherConstructor = launcherClass
.getDeclaredConstructor(archiveClass);
jarLauncherConstructor.setAccessible(true);
Object jarLauncher = jarLauncherConstructor.newInstance(archive);
// Step 4: Invoke launch method
Method launchMethod = launcherClass.getDeclaredMethod("launch", String[].class);
launchMethod.setAccessible(true);
launchMethod.invoke(jarLauncher, new Object[]{args});
}
}
Now let's walk through each step in detail so you understand exactly what's happening under the hood.
Step 1: Create a URLClassLoader
The first thing you need is a ClassLoader that can load classes from your Spring Boot JAR. The standard URLClassLoader does exactly this — you give it the path to your JAR file, and it can load any class contained within it.
File jarFile = new File(jarPath);
URL jarUrl = jarFile.toURI().toURL();
URLClassLoader classLoader = new URLClassLoader(
new URL[]{jarUrl},
SpringBootLauncher.class.getClassLoader()
);
Step 2: Create JarFileArchive
The JarFileArchive class is the key to Spring Boot's executable JAR format. It reads the JAR file structure and provides an interface to its contents. You load this class dynamically using the ClassLoader you just created.
Class> archiveClass = classLoader.loadClass("org.springframework.boot.loader.jar.JarFileArchive");
Constructor> archiveConstructor = archiveClass.getDeclaredConstructor(File.class);
archiveConstructor.setAccessible(true);
Object archive = archiveConstructor.newInstance(jarFile);
Step 3: Create JarLauncher and Launch
The JarLauncher is Spring Boot's bootstrap class. Once you have the archive, you create an instance of JarLauncher (passing the archive to its constructor), then invoke its launch method — which in turn calls your application's main() method.
Constructor> jarLauncherConstructor = launcherClass
.getDeclaredConstructor(archiveClass);
jarLauncherConstructor.setAccessible(true);
Object jarLauncher = jarLauncherConstructor.newInstance(archive);
Method launchMethod = launcherClass.getDeclaredMethod("launch", String[].class);
launchMethod.setAccessible(true);
launchMethod.invoke(jarLauncher, new Object[]{args});
Important note: when you call `launch()`, the current thread will block until the Spring Boot application terminates. If you need the application to run in the background, you'll need to spawn a new thread for the launch call.
Need Help with Spring Boot Implementation?
Our Java team has deep expertise in Spring Boot architecture, including programmatic launch patterns and advanced deployment scenarios.
Talk to Our TeamSimpler Alternative: SpringApplication.run()
If you're not dealing with an executable JAR but rather have access to your application's source code or compiled classes, there's a much simpler approach: directly calling `SpringApplication.run()` or using the `SpringApplicationBuilder` for more control.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
For more control over the application startup — such as disabling the banner, setting specific properties, or configuring the web server — use the SpringApplicationBuilder:
import org.springframework.boot.Banner;
import org.springframework.boot.builder.SpringApplicationBuilder;
new SpringApplicationBuilder(MyApplication.class)
.bannerMode(Banner.Mode.OFF)
.properties("server.port=9090")
.run(args);
When to Use CommandLineRunner Instead
Here's a common misconception: if you need code to run when your Spring Boot application starts, you don't need programmatic launch. The `CommandLineRunner` and `ApplicationRunner` interfaces are designed exactly for this purpose.
Implement these interfaces when you want code to execute after the application context is fully loaded but before the application is considered "ready." This is perfect for initialization tasks, data loading, or warmup operations.
CommandLineRunner: Receives raw String args from main method
ApplicationRunner: Receives parsed ApplicationArguments
@Component
public class StartupRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Application started with args: " + args.getOptionNames());
// Perform initialization tasks here
}
}
How Boundev Solves This for You
Whether you need programmatic launch patterns, advanced Spring Boot configurations, or full-stack Java development, Boundev connects you with developers who have done this before.
Build a dedicated team of Java Spring Boot experts who understand programmatic launch and advanced deployment patterns.
Need Spring Boot expertise fast? Add experienced Java developers to your team in under 72 hours.
Outsource your Spring Boot project entirely. We handle architecture, development, and deployment.
The Bottom Line
Ready to implement Spring Boot programmatic launch?
Boundev's Java team has implemented programmatic launch patterns for test automation, CI/CD pipelines, and microservice orchestration. Let's discuss your use case.
Start BuildingFrequently Asked Questions
What's the difference between CommandLineRunner and ApplicationRunner?
Both interfaces allow you to execute code after the Spring application context is loaded. The key difference is how they receive arguments: CommandLineRunner receives raw String[] args from the main method, while ApplicationRunner receives parsed ApplicationArguments that provide convenient access to option names, values, and non-option arguments.
Why does my programmatic launch need Java reflection?
Spring Boot's executable JAR format stores the Spring Boot Loader classes in a nested JAR structure. These classes (JarFileArchive, JarLauncher) aren't on the classpath by default, so you must load them dynamically using URLClassLoader and Java reflection. This is the same mechanism java -jar uses internally.
How do I launch a Spring Boot app in a background thread?
Since launch() blocks the calling thread until the application terminates, wrap it in a new Thread or use an ExecutorService. Create a Runnable that calls your launch method, submit it to a thread pool, and your main program can continue executing while the Spring Boot app runs in the background.
Can I launch multiple Spring Boot applications from one Java program?
Yes, each launch() call runs in its own ClassLoader instance to avoid class conflicts. Create separate URLClassLoaders for each JAR, load the Spring Boot Loader classes in each, and invoke launch separately. This pattern is commonly used in microservice test harnesses and orchestration frameworks.
What's the simplest way to run code when Spring Boot starts?
Implement the ApplicationRunner or CommandLineRunner interface as a @Component bean. Spring Boot automatically discovers and executes these runners after the application context is refreshed. This is much simpler than programmatic launch and covers most startup task requirements.
Explore Boundev's Services
Need Java Spring Boot expertise for your project? Here's how we can help.
Let's Build This Together
You now understand Spring Boot programmatic launch. The next step is implementation — and that's where Boundev comes in.
200+ companies have trusted us with their Java Spring Boot projects. Tell us what you need — we'll respond within 24 hours.
