JDK11在Linux下如何实现内存预留?未提交预留内存可被其他进程占用吗
JVM线程栈内存观测与Linux内存机制说明
可通过如下命令查看*stack(栈)*的内存占用情况:
jcmd $pid VM.native_memory summary
从命令输出能明显看到reserved(预留内存)和committed(提交内存)的数值差,典型的线程相关内存输出片段如下:
Thread (reserved=18561KB, committed=1085KB) (thread #18) (stack: reserved=18476KB, committed=1000KB) (malloc=63KB #99) (arena=22KB #35)
上面输出里栈的reserved内存约1MB,就是JVM栈的默认大小,只有committed部分才是实际分配了物理内存的部分。Java会给每个线程栈预留完整的内存地址空间,但不会一次性把所有预留内存都提交使用。
用top这类系统命令看进程内存占用的时候,只会统计committed部分的内存量,看不到预留未提交的部分。
测试环境说明:JDK11,Linux操作系统
核心问题解答
1. 预留内存不计入Linux RSS统计的实现原理
这是Linux虚拟内存机制和JVM配合实现的,本质是虚拟地址空间和物理内存分配的解耦设计:
- JVM创建线程栈时,会调用
mmap系统调用申请对应大小的虚拟地址区间,申请时带PROT_NONE权限标记,这一步完全不涉及物理内存分配。内核只会在当前进程的虚拟地址空间管理结构里标记这段地址已经被占用,不会给这段地址映射任何实际物理页帧。 - 只有当线程实际读写栈上的某个地址时,会触发缺页异常(Page Fault),内核陷入异常处理流程后才会给这个地址分配实际物理页,更新页表映射,这部分真正绑定了物理页的内存才会被计入RSS(常驻内存集)。
- RSS本身的统计规则,就是只统计进程已经映射了实际物理内存页的虚拟地址范围,没有绑定物理页的预留虚拟地址,自然不会被纳入统计。
2. 预留未提交的内存是否会被其他进程占用
要分两层理解:
- 从虚拟地址空间维度:不会。预留操作占的是当前进程私有的虚拟地址区间,这段地址在被显式释放前,既不会被当前进程的其他内存申请复用,也不会被其他进程触碰——每个进程的虚拟地址空间是完全隔离的,其他进程根本感知不到这段地址的存在。
- 从物理内存维度:未提交的预留内存完全不占用物理内存,这部分物理内存资源是系统全局共享的,可以被其他进程正常申请使用。
- 这里不存在冲突:当线程后续用到预留的栈地址触发缺页时,内核只要有可用物理内存就会分配新页映射;如果系统物理内存紧张,会先走常规的内存回收流程(回收页缓存、换出不常用的匿名页等),再完成分配,和普通的内存申请逻辑完全一致。
内容的提问来源于stack exchange,提问作者javaTry
相关产品推荐
相关产品推荐

