Spring/Spring Boot

[Spring Boot] 5. Executable Jars

noahkim_ 2023. 10. 13. 19:25

Spring Boot는 spring-boot-loader 모듈을 가지고 executable jar와 war를 로드합니다.

spring-boot-loader 모듈은 build tool의 plugin을 통해 자동으로 셋팅됩니다.

 

Gradle Plugin
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.4'
}
  • java 플러그인이 적용되어 있을 경우, spring boot 플러그인은 spring-boot-loader 모듈을 자동으로 추가합니다.
  • spring-boot-loader 모듈은 executable jar 을 로드하고 실행할 수 있도록 도와주는 역할을 맡습니다.

 

1. Nested JARs

Java는 기본적으로 중첩 jar를 로드하고 압축하는 기능을 제공하지 않습니다.
커맨드라인에서 실행할 수 있는 self-contained 애플리케이션에 대한 필요로 인해 다양한 대안책이 나왔습니다.
 
shaded jar
  • 여러개의 jar들을 하나의 jar에 넣어 uber jar를 만드는 기술입니다.
  • 그러나 이 방법은 다른 library의 이름이 같은 클래스를 로드할 때 예기치 못한 실행이 발생할 수 있습니다.
    • 덮어쓰기, Reflection 에러, 불명확한 오류 추적 등의 오류가 발생합니다.

 

Executable jar
  • Spring Boot는 nested jar를 압축하는 방법으로 Executable jar 기술을 제안하였습니다.
  • Executable jar는 애플리케이션과 그 의존성들을 하나의 jar 파일 안에 패키징하는 방법입니다.
    • spring-boot-loader 모듈을 통해 중첩된 외부 의존성 jar를 로드하고 실행합니다.
    • 이때 외부 의존성 jar를 Loader-Compatible jar라 부릅니다.

 

Executable jar File Structure

 +-META-INF
 |  +-MANIFEST.MF
 +-org
 |  +-springframework
 |     +-boot
 |        +-loader
 |           +-<spring boot loader classes>
 +-BOOT-INF
    +-classes
    |  +-mycompany
    |     +-project
    |        +-YourClasses.class
    +-classpath.idx
    +-layers.idx
    +-lib
       +-dependency1.jar
       +-dependency2.jar

 

 
META-INF
  • jar 파일의 메타데이터를 담고있는 디렉토리입니다.
  • MANIFEST.MF 파일이 포함됩니다.
    • 실제 jar 파일의 메타데이터를 기술한 파일입니다.
Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.koliving.api.KolivingApplication
Spring-Boot-Version: 3.0.4
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
Build-Jdk-Spec: 17
Implementation-Title: api
Implementation-Version: 0.0.1-SNAPSHOT

 

source set (application)
  • 사용자가 개발한 java 파일이 보관된 디렉토리입니다.

 

BOOT-INF
  • executable jar에서 가장 중요한 디렉토리로, 컴파일된 클래스파일, external jars 및 유용한 정보를 가지고 있습니다.
    • classes/ : source set을 컴파일한 class 파일을 가지고 있는 디렉토리입니다.
    • lib/ : external jar이 위치하는 디렉토리입니다.
    • classpath.idx : lib/ 이 담고 있는 external jar의 classpath 정보를 포함하는 파일입니다.
    • layers.idx : 해당 executable jar의 구조 정보가 담긴 파일입니다.

 

2. Spring Boot’s “JarFile” Class

JarFile
  • nested jar 로딩을 담당하는 핵심 클래스입니다.
  • java의 핵심 기능을 사용할 수 있습니다.
    • java 패키지의 클래스를 확장하였습니다.
  • standard jar 혹은 nested child jar 데이터를 로딩합니다.

 

  • 처음 로딩하면, 각각의 로딩된 주소는 outer jar의 offset 값으로 표현됩니다.
    • 내부에서 로딩 주소값을 JarEntry 클래스로 매핑하여 사용합니다.
    • 해당 기능을 사용하여 unpacking하거나 모든 데이터를 읽을 필요가 없습니다.

 

 

3. Launching Executable Jars

Launcher
  • executable jars의 main entry point로 사용되는 특별한 부트스트랩 클래스입니다.
  • 실제로 Main-Class로 설정되어 있습니다.
    • 적절한 URLClassLoader를 설정합니다.
    • 최종적으로 사용자의 main() 메서드를 호출합니다.
  • 해당 클래스는 중첩된 Jar 파일 또는 War 파일의 디렉토리에 있는 리소스를 로드합니다.
    • 각 파일별 서브클래스를 사용하여 로드합니다.

 

Launcher Manifest
  • META-INF/MANIFEST.MF : Jar 파일의 메타데이터를 담고있는 파일입니다.

 

Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.mycompany.project.MyApplication
  • Main-Class
    • Spring Boot의 Launcher 클래스를 지정합니다.
    • Jar 파일이 실행될 때 가장 초기에 로드되는 클래스입니다.
  • Start-Class
    • 실제로 애플리케이션에서 실행하고자 하는 클래스의 이름을 지정합니다.
    • main 메서드를 포함하는 클래스입니다.

 

 

 

 

출처