元空间不存于jvm堆中,它使用本地内存(native memory),即操作系统直接管理的物理内存,与堆完全分离;其逻辑上是方法区的实现,物理上独立于堆,用于存储类元数据,受-xx:maxmetaspacesize限制但不受-xmx影响。

元空间(Metaspace)**不存于JVM堆中**,它使用的是**本地内存(Native Memory)**,也就是操作系统直接管理的物理内存,和JVM堆完全分离。
元空间的物理位置:本地内存,不是堆
从Java 8开始,元空间取代了永久代(PermGen),核心变化之一就是内存归属的迁移:
- JVM堆(Heap)只负责存放对象实例,比如
new Object()创建出来的对象; - 元空间则由HotSpot虚拟机在启动时向操作系统申请本地内存,用于存储类的元数据(如类名、字段、方法字节码、常量池、静态变量等);
- 它不受JVM堆参数(如
-Xmx)控制,也不会出现在堆内存 dump 中。
逻辑归属:它是方法区的实现,但物理上独立
虽然元空间在JVM规范中属于“方法区(Method Area)”这一运行时数据区的逻辑范畴,但它的实现方式彻底脱离了堆:
- 方法区是JVM规范定义的概念,描述“该放什么”;
- 元空间是HotSpot对方法区的具体实现,决定“实际放在哪”——答案是:本地内存;
- 因此,说“元空间在方法区里”是对的(逻辑上),但说“在堆里”是错的(物理上)。
为什么设计成这样?关键好处
把元空间移出堆,主要为了解决永久代时代长期存在的痛点:
- 避免因类加载过多(如热部署、大量反射、OSGi场景)导致
java.lang.OutOfMemoryError: PermGen space; - 取消固定大小限制,默认可动态扩容(上限受物理内存制约);
- 元数据生命周期与类加载器强绑定,类加载器被回收时,其关联的元空间内存才可能被释放——这使内存管理更精准,也减少了不必要的Full GC压力。
如何查看和调优元空间内存
它虽不在堆里,但可通过JVM参数显式干预:
-
-XX:MetaspaceSize=128m:设置元空间首次触发GC的初始阈值(不是初始分配量); -
-XX:MaxMetaspaceSize=512m:硬性限制最大可用空间,防止无节制占用本地内存; - 不设
MaxMetaspaceSize时,元空间会一直增长直到本地内存耗尽,此时抛出OutOfMemoryError: Metaspace; - 可通过
jstat -gc <pid></pid>观察MU(Metaspace used)、MC(Metaspace capacity)等指标。










