Spring Boot项目启动时输出PID、CPU和内存信息的4种方法示例总结

 更新时间:2026年03月09日 09:09:53   作者:bug攻城狮  
本文介绍了四种收集Spring Boot应用启动时输出信息的方法,每种方法都有其适用场景和优缺点,推荐在生产环境中使用Actuator或日志记录方式,感兴趣的朋友跟随小编一起看看吧

方法1:使用Spring Boot Actuator(推荐)

  1. 首先添加依赖:
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
  2. application.yml中启用相关端点:
    # 启用所有端点(或只启用需要的)
    management:
      endpoints:
        web:
          exposure:
            include: '*'  # 暴露所有端点(生产环境慎用)
        health:
          show-details: always  # 显示健康检查详情
        metrics:
          enabled: true
  3. 访问以下端点获取信息:
    • /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项目启动输出内存信息内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java实现电影院订票系统代码

    Java实现电影院订票系统代码

    这篇文章主要介绍了Java实现电影院订票系统代码,代码实现了界面类登录注册类,用户类等,具有一定参考价值,需要的朋友可以参考下。
    2017-11-11
  • Spring如何基于注解配置使用ehcache

    Spring如何基于注解配置使用ehcache

    这篇文章主要介绍了Spring如何基于注解配置使用ehcache,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Springboot如何集成websocket

    Springboot如何集成websocket

    这篇文章主要介绍了Springboot如何集成websocket问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • JAVA关键字及作用详解

    JAVA关键字及作用详解

    本文主要介绍了Java关键字及作用,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • Java根据key获取枚举值的操作方法

    Java根据key获取枚举值的操作方法

    枚举(enum)算一种“语法糖”,是指一个经过排序的、被打包成一个单一实体的项列表,一个枚举的实例可以使用枚举项列表中任意单一项的值,本文给大家介绍了Java 如何快速根据 key 获取枚举的值,需要的朋友可以参考下
    2024-07-07
  • SpringBoot 实现微信扫码登录的示例代码

    SpringBoot 实现微信扫码登录的示例代码

    本文主要介绍使用SpringBoot框架和微信开放平台实现微信扫码登录的功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-10-10
  • 基于Hadoop实现Knn算法

    基于Hadoop实现Knn算法

    这篇文章主要为大家详细 介绍了基于Hadoop实现Knn算法的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • 关于ZooKeeper的会话机制Session解读

    关于ZooKeeper的会话机制Session解读

    这篇文章主要介绍了关于ZooKeeper的会话机制Session解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Java项目打包部署之部署jar包和war包

    Java项目打包部署之部署jar包和war包

    我们在开发环境部署项目一般通过ideal将项目打包成包,然后连接linux服务器,这篇文章主要给大家介绍了关于Java项目打包部署之部署jar包和war包的相关资料,需要的朋友可以参考下
    2023-12-12
  • Java中POST、GET、@RequestBody和@RequestParam区别详析

    Java中POST、GET、@RequestBody和@RequestParam区别详析

    在前后端传json数据进行交互的时候,同学们会经常用到的两个注解,@RequestBody和@RequestParam主要是用来接收前端传给后端的json数据,下面这篇文章主要给大家介绍了关于Java中POST、GET、@RequestBody和@RequestParam区别的相关资料,需要的朋友可以参考下
    2022-10-10

最新评论