Spring Boot 项目在使用内嵌 Tomcat(默认)时的系统资源占用没有固定值,但可以给出典型范围和关键影响因素,帮助你合理评估和优化:
✅ 一、典型资源占用范围(空/最小化应用,JDK 17+,Spring Boot 3.x)
| 资源类型 | 典型范围(启动后稳定态) | 说明 |
|---|---|---|
| JVM 堆内存 (Heap) | 64–256 MB | java -jar app.jar 默认未设 -Xmx 时,HotSpot JVM 通常按物理内存比例分配(如 1/4),但最小约 64MB;简单 REST API 应用常驻堆约 80–120MB。 |
| 总内存占用(RSS) | 120–350 MB | 包含堆 + 元空间(Metaspace)+ 线程栈 + 直接内存 + Tomcat 原生结构等。实测 Spring Boot 3.2 + Web Starter + Actuator 的“Hello World”应用约 180–220 MB(Linux ps aux --sort=-%mem)。 |
| CPU 占用 | < 1%(空闲时) | 无请求时几乎不消耗 CPU;Tomcat 启动线程池(默认 200 线程)处于等待状态,仅少量定时任务(如 Session 清理、Actuator 指标收集)。 |
| 线程数 | 25–40 个 | 内嵌 Tomcat 默认:1 个主线程 + 1 个 Catalina shutdown 线程 + NIO selector 线程(通常 2–4)+ HTTP worker 线程池(默认 maxThreads=200,但实际创建数取决于负载;空闲时仅保留 corePoolSize=10 左右活跃线程 + 几个守护线程)。 |
🔍 示例验证(Linux/macOS):
# 启动最简应用(spring-boot-starter-web + 一个 @RestController) java -jar demo.jar & # 查看 RSS 内存(单位 KB) ps -o pid,rss,comm -p $(pgrep -f "demo.jar") # 输出示例:12345 215680 java → ≈ 215 MB # 查看线程数 ls /proc/$(pgrep -f "demo.jar")/task | wc -l # 输出示例:32
⚙️ 二、影响资源占用的关键因素
| 因素 | 影响说明 | 优化建议 |
|---|---|---|
| 依赖数量 | 每多一个 starter(如 spring-boot-starter-data-jpa, spring-boot-starter-security)会增加类加载、Bean 创建、自动配置开销,显著提升元空间(Metaspace)和堆内存。 |
使用 spring-boot-dependencies 分析依赖树(mvn dependency:tree),移除未用 starter;启用 @ConditionalOnClass 精简自动配置。 |
| Web 容器配置 | Tomcat 默认 maxThreads=200,但线程栈(默认 1MB/线程)会占用大量虚拟内存(VIRT),虽不计入 RSS,但影响容器环境(如 Docker 内存限制)。 |
调整 server.tomcat.threads.max=50;减小栈大小 -Xss256k(需测试稳定性)。 |
| JVM 参数 | 未显式设置 -Xms/-Xmx 会导致堆动态伸缩,GC 频繁;默认 Metaspace 无上限可能 OOM。 |
生产推荐:-Xms256m -Xmx256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m |
| 应用功能复杂度 | 数据库连接池(HikariCP 默认 10 连接)、缓存(Caffeine/Ehcache)、定时任务、WebSocket、Actuator 端点等都会增加内存与线程。 | 关闭不用的 Actuator 端点(management.endpoints.web.exposure.include=health,info);调小连接池 spring.datasource.hikari.maximum-pool-size=5。 |
| JDK 版本 | JDK 17+ 的 ZGC/Shenandoah 或更优的 GC 算法可降低 GC 开销;JDK 21+ 虚拟线程(Project Loom)可大幅减少线程内存占用(需 Tomcat 10.1.15+ 支持)。 | 生产环境优先选用 JDK 17 LTS 或 JDK 21 LTS,搭配合适 GC(如 -XX:+UseZGC)。 |
📊 三、对比参考(实测数据,Linux x64, JDK 17)
| 场景 | RSS 内存 | 线程数 | 说明 |
|---|---|---|---|
最小 Web 应用(仅 spring-boot-starter-web + 1 controller) |
~180 MB | ~28 | 无数据库、无安全、无 Actuator |
| + HikariCP(5 连接) + JPA | ~260 MB | ~35 | 加载 Hibernate、JDBC 驱动、连接池对象 |
| + Spring Security | ~320 MB | ~42 | Security Filter Chain、AuthenticationManager 等 |
| + Actuator 全开启 | ~340 MB | ~45 | Metrics、Health、Env 等端点内存开销 |
💡 提示:使用 Spring Boot DevTools 时,开发阶段内存会额外增加 50–100MB(热重载机制),生产务必排除
devtools。
✅ 四、最佳实践建议
-
始终显式设置 JVM 参数(尤其生产):
java -Xms256m -Xmx256m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:+UseZGC -Dfile.encoding=UTF-8 -jar myapp.jar -
精简依赖:用
spring-boot-starter-webflux替代web(响应式栈更轻量,但适用场景不同);或考虑 GraalVM Native Image(冷启动快、内存≈40–80MB,但构建复杂、反射需配置)。 -
监控基线:启动后用
jstat -gc <pid>观察 GC;用jcmd <pid> VM.native_memory summary查看本地内存分布。 -
容器化注意:Docker 中设置
--memory=512m并配合 JVM 参数,避免因容器内存限制触发 OOM Killer(JVM 无法感知 cgroup 限制,需 JDK 8u191+/10+ 支持-XX:+UseContainerSupport)。
如需进一步优化,可提供你的 pom.xml 或 build.gradle 片段 + 应用功能描述,我可以帮你分析具体瓶颈并给出定制化调优方案。
ECLOUD博客