JVM内存是本地内存的子集,本地内存包含JVM可控内存(堆、元空间、栈等)和不可控系统资源(TCB、文件句柄、native库等),前者受JVM参数限制,后者依赖物理内存与OS限制。

JVM 本地内存(Native Memory)和 JVM 内存(也称 Java 堆内存或虚拟机运行时数据区)不是并列关系,而是包含与被包含的关系:JVM 内存是本地内存的一部分,且仅占其中一小块;其余部分由 JVM 自身运行所需的非堆结构、系统资源等占据。
本地内存是 JVM 进程的全部内存空间
当 JVM 启动时,操作系统会为它分配一块独立的进程地址空间——这就是本地内存。它不等于“堆外内存”,而是一个更宽泛的概念,涵盖 JVM 进程所占用的所有内存,包括:
- JVM 自己管理的部分:堆(Heap)、元空间(Metaspace)、虚拟机栈、本地方法栈、程序计数器、代码缓存(Code Cache)等;
- JVM 不直接管理但必须占用的部分:线程控制块(TCB)、文件描述符、Socket 缓冲区、JNI 加载的 native 库(如 .so/.dll)、JVM 自身的 C++ 对象、GC 线程堆栈等。
JVM 内存受参数控制,本地内存不受参数直接限制
JVM 内存区域(如堆大小 -Xmx、元空间上限 -XX:MaxMetaspaceSize、栈大小 -Xss)可通过启动参数显式设定,超出则抛出 OutOfMemoryError(如 java.lang.OutOfMemoryError: Java heap space)。
而本地内存没有统一的 JVM 参数可设上限,它的总量取决于:
- 物理内存容量和操作系统可用内存;
- 进程地址空间限制(如 Linux 的 ulimit -v 或 32 位进程的 4GB 上限);
- JVM 内部组件实际申请量(例如大量线程会撑大本地栈+TCB,动态生成类会扩大元空间)。
一旦本地内存耗尽,OS 无法再为 JVM 分配页,整个进程会直接崩溃,报错通常是 java.lang.OutOfMemoryError: unable to create new native thread 或 Killed by signal 9 (OOM Killer)(Linux 系统级 OOM 终止)。
直接内存属于本地内存,但不由 JVM 垃圾回收管理
直接内存(Direct Memory) 是本地内存中一个典型子集,通过 ByteBuffer.allocateDirect() 分配,底层调用 malloc 或 mmap 向 OS 申请,绕过 JVM 堆。
- 它不归堆内存参数(-Xmx)管,但受
-XX:MaxDirectMemorySize限制(默认等于 -Xmx); - JVM 不主动回收它,依赖 Cleaner + ReferenceHandler 线程在 ByteBuffer 被 GC 后触发释放;
- 若 Direct Buffer 泄漏(如未 close 或长期持有),会持续占用本地内存,最终拖垮整个 JVM 进程。
元空间是本地内存中 JVM 可配置的关键非堆区域
JDK 8 起,永久代被元空间取代。元空间不再位于 JVM 堆内,而是直接使用本地内存。
- 类定义、常量池、字段/方法元数据都存在元空间;
- 默认无上限(只受本地内存限制),但强烈建议设置
-XX:MaxMetaspaceSize防止失控增长; - 类加载器泄漏(如热部署未清理旧 loader)会导致元空间持续膨胀,也是本地内存溢出的常见原因。

















