Java中类与对象内存分配的核心是类信息存元空间、对象实例存堆、引用存栈;new对象只分配堆内存并存地址到栈,方法代码共用元空间一份,引用赋值为地址共享。

Java 中类与对象的内存分配,核心在于“类信息”和“对象实例”分开存放,且由 JVM 不同区域协同管理。理解这一点,就能理清为什么 new 一个对象不等于复制一份方法代码,也明白为什么两个引用赋值只是地址共享。
类加载后:元空间存结构,堆中无类数据
当你第一次使用某个类(比如 new Cat()),JVM 会先加载该类的字节码。这个过程把类的名称、字段定义、方法签名、常量池等元数据,加载到元空间(Metaspace)——它位于本地内存,不属于 Java 堆。
注意:元空间里不存任何对象实例,也不存静态变量的值(JDK 8+ 静态变量实际存在堆中)。它只存“猫长什么样”的描述,而不是“某只具体的猫”。
new 对象时:堆中分配实例,栈中保存引用
执行 Cat cat1 = new Cat(); 时,发生以下关键动作:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
立即学习“Java免费学习笔记(深入)”;
- JVM 在堆(Heap)中划出一块连续内存,用于存放这个 Cat 实例的数据(如 name、age、color 字段);
- 这块内存开头是对象头,包含哈希码、GC 分代年龄、锁状态,以及一个指向元空间中 Cat 类元数据的指针;
- 字段按声明顺序排列(考虑对齐填充),基本类型直接存值(如 int age = 5),引用类型存4 字节或 8 字节的对象地址(如 String name 指向堆中另一块字符串内容);
- 同时,在当前方法的虚拟机栈中,局部变量表里创建一个名为 cat1 的槽位,里面存的不是猫本身,而是刚才堆中那块内存的地址值。
方法代码在哪?所有对象共用一份
你定义的 public void meow() { ... } 这类成员方法,不会为每个 Cat 对象单独拷贝一份。它们的字节码在类加载时就已存入元空间,所有 Cat 实例调用 meow(),都跳转到同一段指令执行。
也就是说:
– 堆里只放“数据”(字段值 + 对象头);
– 元空间里只放“模板”(类结构 + 方法代码);
– 栈里只放“路标”(对象引用,即地址)。
两个引用指向同一个对象?是地址共享
写 Cat cat2 = cat1;,本质是把栈中 cat1 槽位里的地址值,复制给 cat2 槽位。此时 cat1 和 cat2 指向堆中同一块内存区域。修改 cat1.name,cat2.name 也会变——因为它们读的是同一处字段。
这和数组赋值逻辑一致,不是深拷贝,是浅层的引用传递。

















