JVM 内存解剖:你的服务内存去哪了

「Java 就是吃内存」——先别急着站队。这个页面读取的是正在运行的真实服务的内存现场,把每一份占用都标给你看。

实时采集 · 每 8 秒自动刷新

现场:这份服务此刻的身家

以下数据来自后端 /jvm-memory 接口实测,不是估算。

运行环境:— · GC:—
进程常驻内存 RSS
—
整机视角
堆 已用 / 上限
—
业务对象住这儿
存活线程
—
每条背约 1MB 栈
已加载类
—
Metaspace 的来源
容器内存占用—

账本:每一份内存去了哪

服务启动到现在的稳态分布。绿色之外的彩色块,大部分属于「环境」而非你的业务代码。

拆解:这笔「环境税」都花在哪了

Java 从出厂就把「内存换安全与效率」写进了设计说明书。

一个对象 = 16 字节

new Object() 在堆里就占 16 字节;装箱成 Integer 也是 16 字节。没心疼这些字节,所以你不用操心 C++ 里的 use-after-free。

Metaspace = 类的户口本

开始加载类元数据的地方。Spring 一启动就要解析几百上千个类,Metaspace 跟着涨——这是框架的成本。

Code Cache = 即时编译缓存

JIT 把热点字节码编成机器码存在这里,换的是峰值性能。跑得越热,这里越大。

线程栈 = 人多的代价

每条线程默认背约 1MB 栈。Spring Boot 默认线程池动辄几百线程,虚拟线程(JDK 21)能把这笔砍掉大半。

对照:Spring Boot vs 裸 JDK

用真实可跑的裸 JDK 单文件 HTTP 服务做基准(com.sun.net.httpserver,零依赖,-Xmx64m,启动后约 40–50MB)。

实现常驻内存(RSS)说明
裸 JDK MiniServer(-Xmx64m)≈ 45 MBJDK 11+ 单文件直接跑,百来行代码
本页面背后的 Spring Boot 服务—会话、监控、鉴权、连接池全家桶

所以 Java 真吃内存吗

现象是真的,但锅要甩对地方。

能省

Java Card 几 KB、KVM「千字节虚拟机」跑功能机;裸 JDK 写了也能压到几十 MB。低内存 Java 一直存在。

不是你那个 Spring

服务端没人用裸 JDK——为了省几百 MB 去手动装配事务、鉴权、连接池?没人愿意。这笔省不下来的,叫「环境税」。

都在退环境税

虚拟线程、ZGC、GraalVM native image、Quarkus、Spring Boot 3 官方支持——官方越发力,越说明问题真实存在,解法也一直都有。

内存读数来自此服务自身,本页面不撒谎不预估。想自己验证裸 JDK 那份?拿同一段 MiniServer.java 跑一跑,用 ps -o rss 自己量。