# Exploring the Magic of Spring Boot runnable standalone jar

Spring Boot uses [Spring Boot Gradle Plugin](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin) or [Spring Boot Maven Plugin](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin) to package application as a runnable standalone jar file.

Spring Boot uses the [Spring Boot Loader](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-tools/spring-boot-loader) to lauch the Spring Boot jar file using`java -jar`.

Let's uncompress the jar file and see its structure(jar is actually a zip file):

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1659424262025/cGJwJPwby.png align="left")

We see three sub-folders in the uncompressed folder：`BOOT-INF`,`META-INF`,`org`

```
example.jar
 |
 +-META-INF
 |  +-MANIFEST.MF
 +-org
 |  +-springframework
 |     +-boot
 |        +-loader
 |           +-<spring boot loader classes>
 +-BOOT-INF
    +-classes
    |  +-mycompany
    |     +-project
    |        +-YourClasses.class
    +-lib
       +-dependency1.jar
       +-dependency2.jar
```
**BOOT-INF**
1. `BOOT-INF/classes`: application classes
2. `BOOT-INF/lib`: nested dependency jars
3. `BOOT-INF/classpath.idx`: the ordering that jars should be added to the classpath
4. `BOOT-INF/layers.idx`: allows a jar to be split into logical layers for Docker/OCI image creation

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1659424752998/rwZwd2fdO.png align="left")

**META-INF**

`META-INF/MANIFEST.MF`: contains information about the files contained in the JAR file

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1659424798687/IVpjG5xpJ.png align="left")

**org**

spring boot loader classes

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1659424834494/Uk3QAAqp7.png align="left")

## Explore the Magic
We will explore the steps of running a standalone jar file:
1. `java -jar `
2.  Looking for the executable jar’s main entry point in the `META-INF/MANIFEST.MF`
```
Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: top.wisely.springasync.SpringAsyncApplication
Spring-Boot-Version: 2.7.2
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
```
3. `Main-Class: org.springframework.boot.loader.JarLauncher` is the main entry point.
[JarLauncher](https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/JarLauncher.java)

4. Because`JarLauncher extends ExecutableArchiveLauncher` and `ExecutableArchiveLauncher extends Launcher`

5. `JarLauncher`'s main method:
```java
public class JarLauncher extends ExecutableArchiveLauncher {
//...
	public static void main(String[] args) throws Exception {
		new JarLauncher().launch(args);
	}
//...
}
```
6.  So the real `launch(args)` method is in `Launcher` class:
```java
public abstract class Launcher {
 	protected void launch(String[] args) throws Exception {
		if (!isExploded()) {
			JarFile.registerUrlProtocolHandler(); 
		}
		ClassLoader classLoader = createClassLoader(getClassPathArchivesIterator()); //①
		String jarMode = System.getProperty("jarmode"); 
		String launchClass = (jarMode != null && !jarMode.isEmpty()) ? JAR_MODE_LAUNCHER : getMainClass(); //②
		launch(args, launchClass, classLoader);  //③
	}
}
```

① : `classLoader` - Create a new `LaunchedURLClassLoader` instance. all `BOOT-INF/classes` and `BOOT-INF/jar` classes are loaded by `LaunchedURLClassLoader` .

② : `launchClass` - get the `Start-Class` from `META-INF/MANIFEST.MF`.

③：launch Application using `args`,`launchClass`,`classLoader`.

That'a all for my first English article.

