Spring Boot内存占用高主因是默认配置与JVM、环境不匹配,需先定位堆/元空间/线程栈/直接内存等具体占用区域,再针对性调优而非盲目加大-Xmx。

Spring Boot 项目启动后内存占用高,不是代码写得“重”,而是默认配置、JVM行为和运行环境没对齐。重点不在“加内存”,而在“管住不该占的地方”。
先确认是哪块内存在撑大
别一上来就调 -Xmx。Spring Boot 应用的内存由多部分组成:
- 堆内存(Heap):对象实例、Spring Bean、缓存等——最常被关注,但未必是元凶
- 元空间(Metaspace):存放类定义、方法信息——Starter 多、动态代理多时容易暴涨
- 线程栈内存:每个线程默认占 1MB(Linux x64),Tomcat 默认 200 线程 ≈ 200MB 静态开销
- 直接内存(Direct Buffer):Netty、NIO 文件读写、某些数据库驱动会用,不归 GC 管
快速定位命令:
jcmd <pid> VM.native_memory summary
或启动时加参数看初始分配:java -XX:+PrintCommandLineFlags -version
它会打印 JVM 实际生效的默认堆、元空间等大小,比“我以为”更真实。
JVM 参数必须放对位置才生效
常见错误写法:java -jar app.jar -Xms512m -Xmx1024m
-Xms/-Xmx 被当成了应用参数传给了 main() 方法,完全无效。
正确写法(JVM 参数必须在 -jar 之前):java -Xms128m -Xmx256m -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m -jar app.jar
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
轻量级服务参考值(非硬性):
- 开发/测试环境:-Xms128m -Xmx256m
- 元空间:-XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m(防无限增长)
- 线程栈:-Xss256k(够用且省空间,避免默认1M)
砍掉不必要的自动装配和依赖
Spring Boot 的 “开箱即用” 是双刃剑。一个 spring-boot-starter-web 就带入 Tomcat + JSON + HTTP 完整栈;spring-boot-starter-data-jpa 自动拉 Hibernate + 连接池 + 方言解析器。
检查并精简:
- 用
mvn dependency:tree -Dverbose查重复、无用 starter - 禁用不需要的自动配置:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration - Web 场景若只用 REST API,可换嵌入式 Undertow 或 Jetty,并调小线程池:
server.tomcat.threads.max=50server.tomcat.threads.min-spare=5
排查真实泄漏点,不止看堆
如果内存持续上涨、GC 清不掉,可能是泄漏。分三步:
-
加诊断参数启动:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/dump.hprof -XX:+PrintGCDetails -
用 jstat 看趋势:
jstat -gc <pid> 2s(每2秒刷新),重点关注老年代(Old)是否持续上升、Full GC 是否频繁 - 分析 dump 文件:用 Eclipse MAT 打开 .hprof,看 “Leak Suspects” 报告,或按 “dominator tree” 排序,找长期持有大量对象的静态引用、未关闭的监听器、缓存未过期等
典型泄漏场景包括:
– 静态 Map 缓存用户数据但没清理机制
– 注册了事件监听器或回调但没反注册
– 使用 InputStream/Connection 后没 close()(尤其在 try-with-resources 外手动管理时)

















