Exploring the Magic of Spring Boot runnable standalone jar

Exploring the Magic of Spring Boot runnable standalone jar

Spring Boot uses Spring Boot Gradle Plugin or Spring Boot Maven Plugin to package application as a runnable standalone jar file.

Spring Boot uses the Spring Boot Loader to lauch the Spring Boot jar file usingjava -jar.

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

image.png

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

META-INF

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

image.png

org

spring boot loader classes

image.png

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

  4. BecauseJarLauncher extends ExecutableArchiveLauncher and ExecutableArchiveLauncher extends Launcher

  5. JarLauncher's main method:

    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:
    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.