Files
llm-wiki/raw/official-docs/spring-boot-exit-code-generator-startup-failure.md
T

8.4 KiB

title, source_type, url, archive_url, related_branches, related_projects, tags, created
title source_type url archive_url related_branches related_projects tags created
Spring Boot Exit Code Mechanism — ExitCodeGenerator, ExitCodeExceptionMapper, startup failure path official-doc https://docs.spring.io/spring-boot/reference/features/spring-application.html#features.spring-application.application-exit
feature-migration-startup-contract
ca-skeleton
spring-boot
exit-code
startup-failure
ExitCodeGenerator
ExitCodeExceptionMapper
2026-06-09

Spring Boot Exit Code Mechanism — ExitCodeGenerator, ExitCodeExceptionMapper, startup failure path

Layer: raw/official-docs/ — Spring Boot 공식 참조 문서 + spring-boot-3.4.0-sources.jar 직독.

Parent / 활용 branch (필수)

Branch 이 자료가 정당화하는 결정
raw/branch-notes/feature-migration-startup-contract D7: startup exit code 표준(78/70/71/72)의 Spring Boot 측 메커니즘 — ExitCodeExceptionMapper가 context refresh 실패 시 실제로 호출되는지, 기본 exit code가 무엇인지

출처 / Source

왜 저장했는지 / Why archived

D7 결정(startup exit code = 78/70/71/72)을 구현할 때 Spring Boot가 제공하는 exit code 메커니즘이 실제로 startup failure 시 작동하는지 확인하기 위해 수집. ExitCodeExceptionMapper가 context refresh 실패 시점에 호출 가능한지가 핵심 질문.

핵심 인용 / Key quotes (verbatim)

[§Application Exit] "In addition, beans may implement the ExitCodeGenerator interface if they wish to return a specific exit code when SpringApplication.exit() is called. This exit code can then be passed to System.exit() to return it as a status code."

[§Application Exit] "Also, the ExitCodeGenerator interface may be implemented by exceptions. When such an exception is encountered, Spring Boot returns the exit code provided by the implemented getExitCode() method."

[§Application Exit] "If there is more than one ExitCodeGenerator, the first non-zero exit code that is generated is used. To control the order in which the generators are called, additionally implement the Ordered interface or use the @Order annotation."

[SpringApplication.java:896-899, source] private int getExitCodeFromMappedException(ConfigurableApplicationContext context, Throwable exception) { if (context == null || !context.isActive()) { return 0; } ... }

[SpringApplication.java:1412, source] exitCode = (exitCode != 0) ? exitCode : 1;

Claims Extracted / 추출된 주장

Claim ID Claim (이 자료가 직접 말하는 것) Evidence quote Strength Applies to Does not prove
SB-EXIT-C1 ExitCodeGenerator interface를 implements한 bean은 SpringApplication.exit() 호출 시 지정한 exit code를 반환한다 [§Application Exit] "beans may implement the ExitCodeGenerator interface if they wish to return a specific exit code when SpringApplication.exit() is called" official-vendor-doc Spring Boot 1.0+ 모든 버전 SpringApplication.exit()가 호출되어야 작동함. main()에서 System.exit(SpringApplication.exit(...)) 패턴이 없으면 이 경로가 실행되지 않는다
SB-EXIT-C2 예외 클래스 자체가 ExitCodeGenerator를 구현하면, 그 예외가 발생할 때 해당 exit code가 반환된다 [§Application Exit] "the ExitCodeGenerator interface may be implemented by exceptions. When such an exception is encountered, Spring Boot returns the exit code provided by the implemented getExitCode() method" official-vendor-doc Spring Boot 3.x startup exception chain 내 어떤 위치에서든 작동 (context 의존 없음) ExitCodeExceptionMapper와 달리 context active 상태 불필요 — 단, 예외 클래스를 직접 수정 가능해야 함
SB-EXIT-C3 ExitCodeExceptionMapper는 context == null 또는 !context.isActive() 이면 조회되지 않는다 (exit code 0 반환) [SpringApplication.java:896-899] if (context == null || !context.isActive()) { return 0; } official-vendor-doc (소스코드 직독) Spring Boot 3.4.0. context refresh 실패(BeanCreationException 등)는 isActive()=false에 해당함 ExitCodeExceptionMapper bean이 등록된 경우라도, env 누락처럼 context 생성 이전 실패에는 해당 bean이 조회되지 않음을 증명
SB-EXIT-C4 startup 실패 시 exit code 결정 순서: (1) ExitCodeExceptionMapper (context active 필요), (2) 예외의 ExitCodeGenerator 구현, (3) 둘 다 0이면 최종 fallback = 1 [SpringApplication.java:888-893, 1412] getExitCodeFromMappedExceptiongetExitCodeFromExitCodeGeneratorExceptionexitCode = (exitCode != 0) ? exitCode : 1 official-vendor-doc (소스코드 직독) Spring Boot 3.4.0 startup failure path (handleRunFailure → handleExitCode → getExitCodeFromException) 이 순서는 Spring Boot 버전마다 다를 수 있음. 3.4.0 소스 직독 기준.
SB-EXIT-C5 SpringBootExceptionHandler가 UncaughtExceptionHandler로 등록되어 있어, 커스텀 exit code가 실제로 JVM System.exit()로 전파된다 [SpringBootExceptionHandler.java:49,63] void registerExitCode(int exitCode) { this.exitCode = exitCode; } + if (this.exitCode != 0) { System.exit(this.exitCode); } official-vendor-doc (소스코드 직독) Spring Boot 3.4.0 main thread uncaughtException path 커스텀 exit code가 등록되어야 이 경로가 실행됨. 등록이 0이면 System.exit()가 호출되지 않고 예외가 전파됨
SB-EXIT-C6 Spring Boot 공식 문서는 특정 숫자 exit code (78, 70, 71, 72)를 권장하거나 정의하지 않는다 [§Application Exit] 예시 코드: return () -> 42; — 숫자 선택은 애플리케이션 구현자의 책임 official-vendor-doc 모든 Spring Boot 버전 어떤 숫자를 exit code로 사용해야 하는지는 공식이 규정하지 않음 — sysexits(3) 같은 외부 컨벤션을 따르는 것은 구현자 결정

Usage Boundaries / 적용 경계

  • 이 자료가 직접 증명하는 것:
    • SB-EXIT-C3: ExitCodeExceptionMapper bean은 context refresh 실패 시 호출되지 않음 (context.isActive() = false 조건)
    • SB-EXIT-C2: 예외 클래스 자체가 ExitCodeGenerator를 구현하면 context 상태 무관하게 exit code 적용됨
    • SB-EXIT-C4: 커스텀 exit code 없을 때 기본 fallback = 1
    • SB-EXIT-C5: SpringBootExceptionHandler를 통해 JVM 실제 exit code로 전파됨
  • 이 자료가 증명하지 않는 것:
    • 어떤 숫자를 exit code로 사용해야 하는지 (78, 70, 71, 72 등) — Spring Boot는 숫자 규약을 정의하지 않음 (SB-EXIT-C6)
    • Kubernetes가 이 exit code를 어떻게 처리하는지
    • ExitCodeExceptionMapper bean이 migration failure처럼 context active 상태에서 발생하는 실패에 작동하는지 — 소스 분석에 따르면 작동하지만 ca-tmpl integration test 검증 필요
  • 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
    • env 누락 실패가 실제로 context == null 또는 !isActive() 경로를 타는지 ca-tmpl에서 직접 확인
    • migration failure(Flyway ApplicationRunner)에서 ExitCodeExceptionMapper vs ExitCodeGenerator 중 어느 것이 더 신뢰할 수 있는지 테스트

메모 / Notes

  • ExitCodeExceptionMapper는 graceful shutdown (SpringApplication.exit() 호출)과 ApplicationRunner 실패 시 잘 작동하지만, env 누락처럼 context 생성 이전 실패에는 ExitCodeGenerator 구현이 유일한 방법.
  • Spring Boot가 exit code 숫자 규약을 정의하지 않으므로, 78/70/71/72는 sysexits(3) BSD 컨벤션을 따르는 ca-tmpl 내부 결정임.