// Thread Operations
org.springframework.boot.actuate.management.ThreadDumpEndpoint
// Memory Operations
org.springframework.boot.actuate.management.HeapDumpWebEndpoint
// Startup Tracking
org.springframework.boot.actuate.startup.StartupEndpoint
org.springframework.boot.StartupApplicationStartup
org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup
// SBOM
org.springframework.boot.actuate.sbom.SbomEndpoint
// Lifecycle
org.springframework.boot.actuate.context.ShutdownEndpoint
// Introspection
org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint
org.springframework.boot.actuate.web.mappings.MappingsEndpoint| Endpoint | Operation Type | Risk Level | Default Access | Use When |
|---|---|---|---|---|
| threaddump | Read (Diagnostic) | Medium | Enabled | Deadlock analysis, CPU issues |
| heapdump | Read (Diagnostic) | High | NONE | Memory leaks, OOM debugging |
| startup | Read/Write | Low | Enabled | Slow startup analysis |
| sbom | Read | Low | Enabled | Compliance, security scanning |
| shutdown | Write | Critical | NONE | Graceful shutdown only |
| scheduledtasks | Read | Low | Enabled | Cron job debugging |
| mappings | Read | Low | Enabled | Endpoint discovery |
// ✓ Secure configuration
@Endpoint(id = "heapdump", defaultAccess = Access.NONE) // Disabled by default
@Endpoint(id = "shutdown", defaultAccess = Access.NONE) // Disabled by default
// Explicit enablement required
management:
endpoint:
heapdump:
enabled: true
shutdown:
enabled: true| Operation | CPU Impact | Memory Impact | I/O Impact | Duration |
|---|---|---|---|---|
| threaddump | Low | Low | Low | <1s |
| heapdump | High | High | High | 10s-5min |
| startup | Low | Low | Low | <100ms |
| sbom | Low | Low | Medium | <1s |
| scheduledtasks | Low | Low | Low | <100ms |
| mappings | Low | Medium | Low | <1s |
ThreadDump - Use when:
HeapDump - Use when:
WARNING: HeapDump:
Startup - Use when:
Shutdown - Use when:
DANGER: Never enable shutdown in production without proper security!
PATTERN: Secure shutdown
// ✓ Secure shutdown configuration
management:
endpoint:
shutdown:
enabled: true # Only if needed!
spring:
security:
user:
name: admin
roles: ADMIN
# Security config
@Bean
public SecurityFilterChain shutdownSecurity(HttpSecurity http) {
http.securityMatcher("/actuator/shutdown")
.authorizeHttpRequests(auth -> auth
.anyRequest().hasRole("ADMIN")
);
return http.build();
}ANTI-PATTERN: Unsecured shutdown
# ❌ DANGEROUS!
management:
endpoint:
shutdown:
enabled: true
endpoints:
web:
exposure:
include: shutdown
# No security! Anyone can shut down your app!PATTERN: Heap dump with timeout
// ✓ Configure timeout for large heaps
@Bean
public HeapDumpWebEndpoint heapDumpWebEndpoint() {
return new HeapDumpWebEndpoint(60_000); // 60 seconds
}ANTI-PATTERN: Default timeout on large heap
// ❌ May timeout on large heaps
@Bean
public HeapDumpWebEndpoint heapDumpWebEndpoint() {
return new HeapDumpWebEndpoint(); // 10 second default
}PATTERN: Startup tracking configuration
// ✓ Enable startup tracking
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.setApplicationStartup(new BufferingApplicationStartup(2048));
app.run(args);
}
}Management operations endpoints provide runtime diagnostics and control including thread dumps, heap dumps, startup information, SBOM, shutdown, scheduled tasks inspection, and request mappings analysis.
/**
* Endpoint exposing thread dump information.
*
* Thread-safe: Yes
* Performance: Low impact (<1s typically)
* Since: Spring Boot 2.0+
*/
@Endpoint(id = "threaddump")
public class ThreadDumpEndpoint {
/**
* Get thread dump in JSON format.
*
* @return Thread dump descriptor
*/
@ReadOperation
public ThreadDumpDescriptor threadDump();
/**
* Get thread dump in plain text format.
*
* @return Formatted thread dump
*/
@ReadOperation(produces = "text/plain;charset=UTF-8")
public String textThreadDump();
}
/**
* Thread dump descriptor.
* Contains java.lang.management.ThreadInfo objects.
*/
public static final class ThreadDumpDescriptor implements OperationResponseBody {
public List<ThreadInfo> getThreads();
}/**
* Endpoint for generating heap dumps.
*
* Thread-safe: Yes (but heavy operation!)
* Performance: HIGH impact (10s to minutes)
* Default Access: NONE (disabled by default)
* Since: Spring Boot 2.2+
*
* WARNING: Heap dumps:
* - Pause application during generation
* - Create large files (GBs)
* - Expose all memory contents
* - Heavy I/O and CPU usage
*/
@WebEndpoint(id = "heapdump", defaultAccess = Access.NONE)
public class HeapDumpWebEndpoint {
/**
* Create with default 10 second timeout.
*/
public HeapDumpWebEndpoint();
/**
* Create with custom timeout.
*
* @param timeout Timeout in milliseconds
*/
protected HeapDumpWebEndpoint(long timeout);
/**
* Generate and return heap dump.
*
* @param live Include only live objects (nullable)
* @return Heap dump as downloadable resource
*/
@ReadOperation
public WebEndpointResponse<Resource> heapDump(@Nullable Boolean live);
}/**
* Endpoint exposing application startup timeline.
*
* Thread-safe: Yes
* Requires: BufferingApplicationStartup configured
* Since: Spring Boot 2.4+
*/
@Endpoint(id = "startup")
public class StartupEndpoint {
/**
* Create startup endpoint.
*
* @param applicationStartup Buffering startup tracker
*/
public StartupEndpoint(BufferingApplicationStartup applicationStartup);
/**
* Get startup snapshot (non-destructive).
*
* @return Startup timeline
*/
@ReadOperation
public StartupDescriptor startupSnapshot();
/**
* Get startup timeline and clear buffer (destructive).
*
* @return Startup timeline
*/
@WriteOperation
public StartupDescriptor startup();
}Software Bill of Materials (SBOM) endpoint for exposing software dependencies.
/**
* Endpoint exposing Software Bill of Materials (SBOM) information.
*
* Thread-safe: Yes
* Since: Spring Boot 3.3+
*/
@Endpoint(id = "sbom")
public class SbomEndpoint {
/**
* Create SBOM endpoint.
*
* @param properties SBOM configuration properties
* @param resourceLoader Spring resource loader
*/
public SbomEndpoint(SbomProperties properties, ResourceLoader resourceLoader);
/**
* Get list of available SBOMs.
*
* @return SBOM IDs
*/
@ReadOperation
public Sboms sboms();
/**
* Get specific SBOM by ID.
*
* @param id SBOM identifier
* @return SBOM resource or null if not found
*/
@ReadOperation
public @Nullable Resource sbom(@Selector String id);
/**
* Response containing available SBOM IDs.
*/
public record Sboms(Collection<String> ids) implements OperationResponseBody {}
}
/**
* Web extension for SBOM endpoint providing content-type handling.
*/
@EndpointWebExtension(endpoint = SbomEndpoint.class)
public class SbomEndpointWebExtension {
/**
* Create web extension.
*
* @param sbomEndpoint Delegate SBOM endpoint
* @param properties SBOM properties for media type configuration
*/
public SbomEndpointWebExtension(SbomEndpoint sbomEndpoint, SbomProperties properties);
/**
* Get SBOM with proper content-type header.
*
* @param id SBOM identifier
* @return SBOM resource with HTTP status and content-type
*/
@ReadOperation
public WebEndpointResponse<Resource> sbom(@Selector String id);
}
/**
* Configuration properties for SBOM endpoint.
*/
@ConfigurationProperties("management.endpoint.sbom")
public class SbomProperties {
/**
* Get application SBOM configuration.
*
* @return Application SBOM config
*/
public Sbom getApplication();
/**
* Get additional SBOM configurations.
*
* @return Map of SBOM ID to configuration
*/
public Map<String, Sbom> getAdditional();
/**
* Set additional SBOM configurations.
*
* @param additional SBOM configurations
*/
public void setAdditional(Map<String, Sbom> additional);
/**
* Configuration for a single SBOM.
*/
public static class Sbom {
/**
* Get SBOM file location.
*
* @return File location or null
*/
public @Nullable String getLocation();
/**
* Set SBOM file location.
*
* @param location File location
*/
public void setLocation(@Nullable String location);
/**
* Get SBOM media type.
*
* @return Media type or null for auto-detection
*/
public @Nullable MimeType getMediaType();
/**
* Set SBOM media type.
*
* @param mediaType Media type
*/
public void setMediaType(@Nullable MimeType mediaType);
}
}Graceful application shutdown endpoint.
/**
* Endpoint for gracefully shutting down the application.
*
* Thread-safe: Yes
* Default Access: NONE (disabled by default for safety)
* Since: Spring Boot 2.0+
*
* WARNING: Enables remote shutdown of application!
* Only enable when:
* - Behind proper authentication
* - In controlled environments
* - With appropriate security measures
*/
@Endpoint(id = "shutdown", defaultAccess = Access.NONE)
public class ShutdownEndpoint implements ApplicationContextAware {
/**
* Shutdown the application gracefully.
*
* @return Shutdown descriptor with status message
*/
@WriteOperation
public ShutdownDescriptor shutdown();
}
/**
* Descriptor for shutdown operation result.
*/
public static final class ShutdownDescriptor implements OperationResponseBody {
public String getMessage();
}Introspection endpoint for viewing scheduled tasks.
/**
* Endpoint exposing information about scheduled tasks.
*
* Thread-safe: Yes
* Since: Spring Boot 2.0+
*/
@Endpoint(id = "scheduledtasks")
public class ScheduledTasksEndpoint {
/**
* Create endpoint.
*
* @param scheduledTaskHolders Holders for scheduled tasks
*/
public ScheduledTasksEndpoint(Collection<ScheduledTaskHolder> scheduledTaskHolders);
/**
* Get all scheduled tasks.
*
* @return Descriptor of all scheduled tasks
*/
@ReadOperation
public ScheduledTasksDescriptor scheduledTasks();
}
/**
* Descriptor containing scheduled task information.
*/
public static final class ScheduledTasksDescriptor implements OperationResponseBody {
public List<CronTaskDescriptor> getCron();
public List<FixedDelayTaskDescriptor> getFixedDelay();
public List<FixedRateTaskDescriptor> getFixedRate();
}Introspection endpoint for viewing request mappings.
/**
* Endpoint exposing HTTP request mappings.
*
* Thread-safe: Yes
* Supports: Spring MVC and WebFlux
* Since: Spring Boot 2.0+
*/
@Endpoint(id = "mappings")
public class MappingsEndpoint {
/**
* Create endpoint.
*
* @param descriptionProviders Providers for mapping descriptions
* @param context Application context
*/
public MappingsEndpoint(Collection<MappingDescriptionProvider> descriptionProviders,
ApplicationContext context);
/**
* Get all request mappings.
*
* @return Descriptor of all mappings across contexts
*/
@ReadOperation
public ApplicationMappingsDescriptor mappings();
}
/**
* Provider for mapping descriptions.
* Implement this interface to provide custom mapping information.
*
* Thread-safe: Implementation dependent
* Package: org.springframework.boot.actuate.web.mappings
* @since 2.0.0
*/
public interface MappingDescriptionProvider {
/**
* Get the name of the mappings described by this provider.
*
* @return Mapping name (e.g., "dispatcherServlets", "dispatcherHandlers")
*/
String getMappingName();
/**
* Produce the descriptions of the mappings identified by this provider in the given context.
*
* @param context Application context to introspect
* @return Mapping descriptions (type depends on implementation)
*/
Object describeMappings(ApplicationContext context);
}
/**
* A description of a HandlerMethod.
* Provides metadata about controller handler methods including name, descriptor, and class.
*
* Thread-safe: Yes (immutable)
* Package: org.springframework.boot.actuate.web.mappings
* @since 2.0.0
*/
public class HandlerMethodDescription {
/**
* Creates a new HandlerMethodDescription for the given handler method.
*
* @param handlerMethod Handler method to describe
*/
public HandlerMethodDescription(HandlerMethod handlerMethod);
/**
* Returns the name of the handler method.
*
* @return Method name
*/
public String getName();
/**
* Returns the descriptor of the handler method.
* The descriptor provides a signature-like representation of the method.
*
* @return Method descriptor
*/
public String getDescriptor();
/**
* Returns the fully qualified name of the class that declares the handler method.
*
* @return Class name
*/
public String getClassName();
}
/**
* Descriptor containing all application mappings.
*/
public static final class ApplicationMappingsDescriptor implements OperationResponseBody {
public Map<String, ContextMappingsDescriptor> getContexts();
}package com.example.actuator;
import org.springframework.boot.actuate.management.ThreadDumpEndpoint;
import org.springframework.stereotype.Service;
import java.lang.management.ThreadInfo;
import java.util.*;
import java.util.stream.Collectors;
/**
* Service for analyzing thread dumps.
*
* Thread-safe: Yes
* Since: Application 1.0
*/
@Service
public class ThreadAnalysisService {
private final ThreadDumpEndpoint threadDumpEndpoint;
public ThreadAnalysisService(ThreadDumpEndpoint threadDumpEndpoint) {
this.threadDumpEndpoint = threadDumpEndpoint;
}
/**
* Detect deadlocks in application.
*
* @return List of deadlocked thread IDs
*/
public List<Long> detectDeadlocks() {
ThreadDumpEndpoint.ThreadDumpDescriptor dump = threadDumpEndpoint.threadDump();
return dump.getThreads().stream()
.filter(thread -> thread.getLockOwnerId() != -1)
.map(ThreadInfo::getThreadId)
.collect(Collectors.toList());
}
/**
* Find blocked threads.
*
* @return List of blocked thread names
*/
public List<String> findBlockedThreads() {
ThreadDumpEndpoint.ThreadDumpDescriptor dump = threadDumpEndpoint.threadDump();
return dump.getThreads().stream()
.filter(thread -> thread.getThreadState() == Thread.State.BLOCKED)
.map(ThreadInfo::getThreadName)
.collect(Collectors.toList());
}
/**
* Get thread state distribution.
*
* @return Map of states to counts
*/
public Map<Thread.State, Long> getThreadStateDistribution() {
ThreadDumpEndpoint.ThreadDumpDescriptor dump = threadDumpEndpoint.threadDump();
return dump.getThreads().stream()
.collect(Collectors.groupingBy(
ThreadInfo::getThreadState,
Collectors.counting()
));
}
/**
* Find threads waiting longest.
*
* @param limit Number of results
* @return List of thread names with wait times
*/
public List<ThreadWaitInfo> findLongestWaitingThreads(int limit) {
ThreadDumpEndpoint.ThreadDumpDescriptor dump = threadDumpEndpoint.threadDump();
return dump.getThreads().stream()
.filter(thread -> thread.getWaitedTime() > 0)
.sorted(Comparator.comparingLong(ThreadInfo::getWaitedTime).reversed())
.limit(limit)
.map(thread -> new ThreadWaitInfo(
thread.getThreadName(),
thread.getWaitedTime(),
thread.getThreadState().toString()
))
.collect(Collectors.toList());
}
public record ThreadWaitInfo(String name, long waitedTimeMs, String state) {}
}package com.example.actuator;
import org.springframework.boot.actuate.management.HeapDumpWebEndpoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
/**
* Configuration for heap dump endpoint.
*
* IMPORTANT: Heap dumps are DISABLED by default.
* Only enable if absolutely necessary and properly secured.
*
* Since: Application 1.0
*/
@Configuration
public class HeapDumpConfiguration {
/**
* Configure heap dump endpoint with extended timeout.
* For large heaps (>4GB), increase timeout accordingly.
*
* @return Configured endpoint
*/
@Bean
public HeapDumpWebEndpoint heapDumpWebEndpoint() {
// 60 second timeout for large heaps
return new HeapDumpWebEndpoint(60_000);
}
/**
* CRITICAL: Secure heap dump endpoint.
* Heap dumps contain ALL application memory including:
* - Passwords and credentials
* - Session tokens
* - User data
* - Business logic state
*
* @param http HTTP security
* @return Security filter chain
*/
@Bean
public SecurityFilterChain heapDumpSecurity(HttpSecurity http) throws Exception {
http.securityMatcher("/actuator/heapdump")
.authorizeHttpRequests(auth -> auth
.anyRequest().hasRole("ADMIN")
);
return http.build();
}
}
// Enable in application.yml (only if needed!)
/*
management:
endpoint:
heapdump:
enabled: true # DANGEROUS - only enable if secured!
timeout: 60000
spring:
security:
user:
name: admin
password: ${ADMIN_PASSWORD}
roles: ADMIN
*/
// Usage:
// GET /actuator/heapdump → Full heap dump
// GET /actuator/heapdump?live=true → Live objects only (smaller)
// Analyze with:
// - Eclipse Memory Analyzer (MAT)
// - VisualVM
// - JProfilerpackage com.example.actuator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
import org.springframework.boot.actuate.startup.StartupEndpoint;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Application with startup tracking enabled.
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
// Enable startup tracking (capacity = number of steps to track)
app.setApplicationStartup(new BufferingApplicationStartup(2048));
app.run(args);
}
}
/**
* Service for analyzing startup timeline.
*
* Thread-safe: Yes
* Since: Application 1.0
*/
@Service
public class StartupAnalysisService {
private final StartupEndpoint startupEndpoint;
public StartupAnalysisService(StartupEndpoint startupEndpoint) {
this.startupEndpoint = startupEndpoint;
}
/**
* Get slow startup steps.
*
* @param thresholdMs Threshold in milliseconds
* @return List of slow steps
*/
public List<SlowStartupStep> findSlowSteps(long thresholdMs) {
StartupEndpoint.StartupDescriptor startup = startupEndpoint.startupSnapshot();
// Note: Actual timeline structure depends on Spring Boot version
// This is a simplified example
return List.of(); // Implementation depends on timeline structure
}
/**
* Get total startup time.
*
* @return Startup duration
*/
public Duration getTotalStartupTime() {
StartupEndpoint.StartupDescriptor startup = startupEndpoint.startupSnapshot();
// Access timeline.duration() based on actual structure
return Duration.ZERO; // Simplified
}
public record SlowStartupStep(String name, Duration duration) {}
}
// Access startup data:
// GET /actuator/startup → Returns timeline and clears buffer
// GET /actuator/startup/snapshot → Returns timeline without clearingpackage com.example.actuator;
import org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* Service for inspecting scheduled tasks.
*
* Thread-safe: Yes
* Since: Application 1.0
*/
@Service
public class ScheduledTasksInspectionService {
private final ScheduledTasksEndpoint endpoint;
public ScheduledTasksInspectionService(ScheduledTasksEndpoint endpoint) {
this.endpoint = endpoint;
}
/**
* Get all cron tasks.
*
* @return List of cron expressions
*/
public List<String> getAllCronExpressions() {
ScheduledTasksEndpoint.ScheduledTasksDescriptor tasks = endpoint.scheduledTasks();
return tasks.getCron().stream()
.map(task -> task.getExpression())
.collect(Collectors.toList());
}
/**
* Get all fixed-rate tasks with intervals.
*
* @return List of task info
*/
public List<FixedRateTaskInfo> getFixedRateTasks() {
ScheduledTasksEndpoint.ScheduledTasksDescriptor tasks = endpoint.scheduledTasks();
return tasks.getFixedRate().stream()
.map(task -> new FixedRateTaskInfo(
task.getRunnable().getTarget(),
task.getInterval()
))
.collect(Collectors.toList());
}
public record FixedRateTaskInfo(String target, long intervalMs) {}
}package com.example.actuator;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.boot.actuate.management.ThreadDumpEndpoint;
import java.util.Map;
import static org.assertj.core.api.Assertions.*;
class ThreadAnalysisServiceTest {
private ThreadDumpEndpoint endpoint;
private ThreadAnalysisService service;
@BeforeEach
void setUp() {
endpoint = new ThreadDumpEndpoint();
service = new ThreadAnalysisService(endpoint);
}
@Test
void getThreadStateDistribution_ReturnsDistribution() {
Map<Thread.State, Long> distribution = service.getThreadStateDistribution();
assertThat(distribution).isNotEmpty();
assertThat(distribution.values().stream().mapToLong(Long::longValue).sum())
.isGreaterThan(0);
}
@Test
void findBlockedThreads_ReturnsListWithoutErrors() {
List<String> blocked = service.findBlockedThreads();
assertThat(blocked).isNotNull();
// May be empty if no threads blocked
}
}Problem: Heap dump request times out
Causes:
Solutions:
// Solution 1: Increase timeout
@Bean
public HeapDumpWebEndpoint heapDumpWebEndpoint() {
// For 8GB heap, use 2-3 minute timeout
return new HeapDumpWebEndpoint(180_000);
}
// Solution 2: Use live=true for smaller dump
// GET /actuator/heapdump?live=true
// Solution 3: Ensure sufficient disk space
// Heap dump size ≈ heap usageProblem: /actuator/startup returns empty or error
Causes:
Solutions:
// Solution 1: Configure startup tracking
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.setApplicationStartup(new BufferingApplicationStartup(2048));
app.run(args);
}
}
// Solution 2: Use snapshot endpoint (non-destructive)
// GET /actuator/startup/snapshot
// Solution 3: Increase capacity if needed
new BufferingApplicationStartup(4096)Problem: POST /actuator/shutdown has no effect
Causes:
Solutions:
# Solution 1: Enable endpoint
management:
endpoint:
shutdown:
enabled: true
# Solution 2: Check security config
# Ensure user has required role
# Solution 3: Check logs for shutdown process// Thread dumps are relatively lightweight
// - Typically <1 second
// - Low memory overhead
// - No application pause (modern JVMs)
// Safe to call during production issues
// Use for:
// - Deadlock detection
// - CPU spike investigation
// - Thread pool exhaustion// Heap dumps are VERY expensive:
// - Pauses application (STW)
// - Duration: 10s to several minutes
// - Creates files = heap size
// - High I/O and CPU usage
// Typical timings:
// 1GB heap: ~10-30 seconds
// 4GB heap: ~1-2 minutes
// 16GB heap: ~5-10 minutes
// NEVER use in production without:
// 1. Maintenance window
// 2. Load balancer removes instance
// 3. Sufficient disk space
// 4. Extended timeout configured// BufferingApplicationStartup has minimal overhead:
// - ~1-2ms total overhead
// - Small memory footprint
// - No runtime impact after startup
// Safe to enable in production
BufferingApplicationStartup startup =
new BufferingApplicationStartup(2048); // ~100KB memory