Spring Boot项目启动时输出PID、CPU和内存信息的4种方法示例总结
作者:bug攻城狮
本文介绍了四种收集Spring Boot应用启动时输出信息的方法,每种方法都有其适用场景和优缺点,推荐在生产环境中使用Actuator或日志记录方式,感兴趣的朋友跟随小编一起看看吧
方法1:使用Spring Boot Actuator(推荐)
- 首先添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
- 在
application.yml中启用相关端点:# 启用所有端点(或只启用需要的) management: endpoints: web: exposure: include: '*' # 暴露所有端点(生产环境慎用) health: show-details: always # 显示健康检查详情 metrics: enabled: true - 访问以下端点获取信息:
/actuator/info- 基本信息/actuator/health- 健康状态/actuator/metrics- 各种指标/actuator/metrics/system.cpu.usage- CPU使用率/actuator/metrics/jvm.memory.used- JVM内存使用
方法2:自定义启动时输出(简单直接)
在Spring Boot主类或配置类中添加:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.annotation.PostConstruct;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
@SpringBootApplication
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
@PostConstruct
public void printSystemInfo() {
// 获取PID
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
String jvmName = runtimeBean.getName();
long pid = Long.parseLong(jvmName.split("@")[0]);
// 内存信息
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();
long allocatedMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
// 输出信息
System.out.println("\n==========================================");
System.out.println(" Application System Information");
System.out.println("==========================================");
System.out.println(" PID: " + pid);
System.out.println(" CPU Cores: " + runtime.availableProcessors());
System.out.println(" Memory Info:");
System.out.println(" - Max: " + maxMemory / 1024 / 1024 + " MB");
System.out.println(" - Allocated: " + allocatedMemory / 1024 / 1024 + " MB");
System.out.println(" - Free: " + freeMemory / 1024 / 1024 + " MB");
System.out.println(" - Used: " + (allocatedMemory - freeMemory) / 1024 / 1024 + " MB");
System.out.println("==========================================\n");
}
}方法3:使用Logback/SLF4J输出(生产环境推荐)
在logback-spring.xml配置中添加:
<configuration>
<!-- 1. 从Spring环境变量中获取应用名称 -->
<springProperty name="app.name" source="spring.application.name" defaultValue="spring-boot-app"/>
<!-- 2. 定义控制台日志输出格式 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 日志格式:时间 + 线程 + 日志级别 + 类名 + 消息 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 3. 设置根日志级别和输出目标 -->
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
<!-- 4. 定义SystemInfoLogger Bean并指定初始化方法 -->
<bean id="systemInfoLogger" class="com.your.package.SystemInfoLogger" init-method="logSystemInfo"/>
</configuration>如果使用的是 logback.xml(而非 logback-spring.xml)并遇到 <bean> 标签启动报错,这是因为 Logback 原生配置不支持直接定义 Spring Bean。问题根源在于配置文件的解析机制不同:
logback.xml:由 Logback 原生解析,不支持 Spring 的<bean>标签logback-spring.xml:由 Spring Boot 解析,扩展了 Spring 的 XML 命名空间,支持<springProperty>和<bean>等标签
如果将 logback.xml 重命名为 logback-spring.xml,Spring Boot 仍然没有正确解析 <bean> 标签,可以使用下面的替代方案。
然后创建对应的Java类:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
@Component
public class SystemInfoLogger {
// 1. 通过SLF4J获取Logger实例
private static final Logger logger = LoggerFactory.getLogger(SystemInfoLogger.class);
// 2. Bean初始化后调用的方法
public void logSystemInfo() {
// 3. 获取PID(通过RuntimeMXBean)
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
long pid = Long.parseLong(runtimeBean.getName().split("@")[0]);
// 4. 获取内存信息(通过Runtime)
Runtime runtime = Runtime.getRuntime();
long usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024;
// 5. 格式化输出到日志(使用占位符{}避免字符串拼接)
logger.info("\n" +
"=========================================\n" +
" Application: {}\n" +
" PID: {}\n" +
" CPU Cores: {}\n" +
" Memory:\n" +
" - Max: {} MB\n" +
" - Total: {} MB\n" +
" - Free: {} MB\n" +
" - Used: {} MB\n" +
"=========================================",
System.getProperty("spring.application.name", "Spring Boot Application"),
pid,
runtime.availableProcessors(),
runtime.maxMemory() / 1024 / 1024,
runtime.totalMemory() / 1024 / 1024,
runtime.freeMemory() / 1024 / 1024,
usedMemory
);
}
}替代方案
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
@Component
public class SystemInfoPrinter implements ApplicationListener<ContextRefreshedEvent> {
// 通过SLF4J获取Logger实例,用于记录日志信息
private static final Logger logger = LoggerFactory.getLogger(SystemInfoPrinter.class);
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
// 获取PID(通过RuntimeMXBean)
long pid = Long.parseLong(runtimeBean.getName().split("@")[0]);
Runtime runtime = Runtime.getRuntime();
// 格式化输出到日志(使用占位符{}避免字符串拼接)
logger.info("\n" +
"=========================================\n" +
" Application: {}\n" +
" PID: {}\n" +
" CPU Cores: {}\n" +
" Memory:\n" +
" - Max: {} MB\n" +
" - Total: {} MB\n" +
" - Free: {} MB\n" +
" - Used: {} MB\n" +
"=========================================",
System.getProperty("spring.application.name", "Spring Boot Application"),
pid,
runtime.availableProcessors(),
runtime.maxMemory() / 1024 / 1024,
runtime.totalMemory() / 1024 / 1024,
runtime.freeMemory() / 1024 / 1024,
(runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024
);
}
}知识拓展:@PostConstruct与ApplicationListener差异
1. 核心异同对比表
| 特性 | ApplicationListener | @PostConstruct |
|---|---|---|
| 触发时机 | Spring上下文完全刷新后(所有Bean初始化完成) | Bean自身初始化完成后(依赖注入之后) |
| 执行顺序 | 较晚(确保所有Bean可用) | 较早(当前Bean初始化后立即执行) |
| 事件类型 | 响应ContextRefreshedEvent事件 | 基于JSR-250标准注解 |
| 适用场景 | 需要访问其他完全初始化的Bean时 | 只需当前Bean自身资源的场景 |
| 多次执行风险 | 可能触发多次(重复上下文刷新时) | 仅执行一次 |
| Spring版本兼容性 | 所有Spring版本 | 需Spring 2.5+(支持JSR-250) |
| 日志输出可靠性 | 更高(确保日志系统已初始化) | 可能因日志系统未完全初始化导致输出丢失(极少数情况) |
2. 执行时机差异图解
Spring启动流程: 1. 创建Bean实例 └─ 方案二@PostConstruct执行 ← 此时部分依赖可能未就绪 2. 依赖注入 3. 初始化回调 4. 发布ContextRefreshedEvent └─ 方案一ApplicationListener执行 ← 此时所有Bean已就绪
方法4:使用第三方库(如oshi)
添加依赖:
<dependency> <groupId>com.github.oshi</groupId> <artifactId>oshi-core</artifactId> <version>6.4.0</version> </dependency>
然后使用:
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.HardwareAbstractionLayer;
public void printDetailedSystemInfo() {
SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
CentralProcessor processor = hal.getProcessor();
System.out.println("CPU: " + processor.getProcessorIdentifier().getName());
System.out.println("Physical CPUs: " + processor.getPhysicalProcessorCount());
System.out.println("Logical CPUs: " + processor.getLogicalProcessorCount());
System.out.println("CPU Load: " + hal.getProcessor().getSystemLoadAverage());
}输出示例
无论使用哪种方法,启动后你将看到类似这样的输出:
========================================== Application System Information ========================================== PID: 12345 CPU Cores: 8 Memory Info: - Max: 4096 MB - Allocated: 1024 MB - Free: 756 MB - Used: 268 MB ==========================================
这些方法可以根据你的需求选择使用,对于生产环境,推荐使用方法1(Actuator)或方法3(日志记录)。
到此这篇关于Spring Boot项目启动时输出PID、CPU和内存信息的4种方法的文章就介绍到这了,更多相关springboot项目启动输出内存信息内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
