Spring Boot Microservice Auto‑Exit After Startup: Diagnosis and Fixes

The article analyzes why a Spring Boot microservice may start and then terminate instantly without logs, covering JVM memory misconfiguration, dependency conflicts, configuration file errors, and compatibility issues, and provides step‑by‑step diagnostic commands, code examples, and practical remediation strategies.

Programmer1970
Programmer1970
Programmer1970
Spring Boot Microservice Auto‑Exit After Startup: Diagnosis and Fixes

Problem Overview

Spring Boot microservices sometimes start and then exit immediately. Symptoms include silent console, process disappears, startup method agnostic, and environment agnostic.

Diagnostic Framework and Solutions

1. No log output – JVM‑level faults

Typical characteristics: process terminates immediately, no Spring logs, exit code often 143 (SIGTERM) or 137 (SIGKILL).

Diagnostic path:

JVM memory parameter verification

Check physical memory: free -h (ensure -Xmx does not exceed available memory).

Validate memory flags: java -XX:+PrintFlagsFinal -version | grep -i heapsize Example failure on a 4 GB machine with 9 GB heap:

# 4C8G机器配置9G堆内存(必然失败)
java -Xms4g -Xmx9g -jar app.jar

GC strategy compatibility check

Conflict scenario: configuring both G1 and Parallel GC.

Verification command:

jcmd <PID> VM.flags | grep -E "GarbageCollector|HeapDumpPath"

Solution example in application.yml:

spring:
  jvm:
    gc:
      name: G1GC
      params: "-XX:+UseG1GC -XX:MaxGCPauseMillis=200"

System resource limits

File descriptor limit: ulimit -n Process count limit: cat /proc/sys/kernel/pid_max Temporary fix:

# 临时调整
ulimit -n 65535
# 永久生效需修改 /etc/security/limits.conf

2. Exit code 1 – Framework initialization failure

Typical characteristics: only Spring version information is printed, exit code 1, --debug reveals more details.

Diagnostic steps:

Dependency management issues

Detect conflicts with: mvn dependency:tree -Dverbose -Dincludes=org.springframework Typical conflict: multiple Spring Boot versions.

<!-- 错误配置:多版本Spring Boot依赖 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <version>2.3.4.RELEASE</version>
</dependency>
<!-- 与父POM声明的2.7.0冲突 -->

Resolution using dependencyManagement import:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.7.5</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Configuration file parsing errors

YAML indentation mistake example:

# 错误:缩进错误
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test  # 缩进错误

Property override detection:

# 检查环境变量覆盖
env | grep SPRING_

Log framework conflicts

Conflict matrix (summary):

SLF4J bridge conflict → Multiple binding warning → Exclude the conflicting dependency.

Log4j2 config failure → No log output → Add jcl-over-slf4j bridge.

Mixed logging frameworks → Chaotic output → Consolidate to a single logging implementation.

Example Maven exclusion to remove Log4j2 binding:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-log4j2</artifactId>
  <exclusions>
    <exclusion>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
    </exclusion>
  </exclusions>
</dependency>

3. Exit code 0 – Compatibility issues

Typical characteristics: program appears to run then exits, exit code 0, service registration (e.g., Eureka) does not actually happen.

Diagnostic dimensions:

Component compatibility check

Servlet container conflict example (duplicate Tomcat dependencies):

<!-- 错误:重复包含Tomcat -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-core</artifactId>
  <version>9.0.65</version>
  <!-- 版本冲突 -->
</dependency>

Resolution: declare Tomcat starter with provided scope:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-tomcat</artifactId>
  <scope>provided</scope>
</dependency>

Spring Boot version compatibility

Version matrix:

Spring Boot 2.7.x → JDK 8+ → Tomcat 9.0

Spring Boot 3.0.x → JDK 17+ → Tomcat 10.1

Migration suggestion (properties):

<properties>
  <java.version>17</java.version>
  <spring-boot.version>3.0.2</spring-boot.version>
</properties>

Environment variable loading failures

Profile activation detection:

# 检查激活的Profile
curl -s http://localhost:8080/actuator/env | grep activeProfiles

Config server connection verification (Spring Cloud):

spring:
  cloud:
    config:
      uri: http://config-server:8888
      fail-fast: true
      retry:
        max-attempts: 6

Diagnostic Toolset

JVM‑level diagnostics

Heap dump:

java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -jar app.jar

Thread dump:

jstack <PID> > /tmp/thread-dump.log

Spring Boot specific tools

Actuator endpoints:

GET /actuator/health
GET /actuator/env
GET /actuator/mappings

Startup debug flags:

java -jar app.jar --debug --trace

Containerized environment diagnostics

Docker resource inspection:

docker stats <container_id>
docker inspect <container_id> | grep -i memory

Practical Recommendations

Standardize startup scripts

#!/bin/bash
export SPRING_PROFILES_ACTIVE=prod
export JAVA_OPTS="-Xms512m -Xmx2048m -XX:+UseG1GC"
java $JAVA_OPTS -jar app.jar >> /var/log/app.log 2>&1

Dependency management best practices

Lock versions with dependencyManagement.

Run mvn dependency:analyze to detect unused or conflicting dependencies.

Health‑check endpoint

@RestController
public class HealthController {
    @GetMapping("/ready")
    public ResponseEntity<String> readiness() {
        return ResponseEntity.ok("OK");
    }
}

Logging strategy optimization

# application.yml configuration
logging:
  level:
    root: INFO
    org.springframework: DEBUG
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

Summary

Use a layered diagnosis method: start from JVM parameters, then dependency conflicts, and finally configuration files.

Leverage tools such as jcmd, Actuator endpoints, and memory‑dump analyzers for deep analysis.

Maintain a disciplined version‑control and dependency‑management process to avoid incompatibilities.

Standardize environment configurations across development, testing, and production to ensure consistent behavior.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JVMDockerdependency-managementSpring Bootdiagnosticsmicroserviceactuator
Programmer1970
Written by

Programmer1970

Formerly called 'Code to 35'. Add our main WeChat ID to access a wealth of shared resources (algorithms, interview prep, tech stacks: Java, Python, Go, big data). We mainly share serious development techniques, focusing on output-driven input. Occasionally we post life snippets and gossip. Our aim is to attract precise traffic and test advertising opportunities.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.