runtime.getruntime().maxmemory() 获取的是 jvm 堆内存理论最大容量(单位字节),对应 -xmx 值,不包括元空间、直接内存、线程栈等非堆区域;在容器中若未启用 -xx:+usecontainersupport,仍可能误读宿主机内存。

Runtime.getRuntime().maxMemory() 获取的是 JVM 堆内存(Heap)的理论最大容量,单位为字节,对应启动参数 -Xmx 的设定值。
它只反映堆内存上限
这个值不包括以下任何部分:
- 元空间(Metaspace),由
-XX:MaxMetaspaceSize控制 - 直接内存(Direct Memory),受
-XX:MaxDirectMemorySize限制 - 线程栈(Thread Stack),由
-Xss决定 - 代码缓存(CodeCache)、JVM 自身开销等非堆区域
它不是物理内存或容器内存的真实额度
在容器(如 Docker、Kubernetes)中,若未启用容器内存感知支持,maxMemory() 仍可能读取宿主机总内存并据此推导默认 -Xmx,导致返回值远高于容器实际可用内存。要让其正确反映容器限制,需满足:
- JDK 8u191+ 或 JDK 10+,且显式添加
-XX:+UseContainerSupport - 或 JDK 10+ 默认已开启该选项(但需确认未被禁用)
它在 JVM 启动后基本固定
即使使用 G1 等垃圾收集器动态调整堆大小,maxMemory() 始终返回初始配置的上限值(即 -Xmx),不会随 totalMemory() 的增长而变化。例如:
- 启动时加
-Xms256m -Xmx2g,则maxMemory()恒为约 2,147,483,648 字节 - 无论当前
totalMemory()是 256MB 还是 1.5GB,该值不变
它和真实可用内存有差距
该值是“理论上可申请的最大堆字节数”,但实际能否分配成功还取决于:
- 操作系统是否还能提供连续虚拟内存页
- 是否存在内存碎片(尤其 CMS 或 Serial GC 下)
- 是否触发了 Native OOM(如直接内存耗尽,不影响堆上限判断)











