类存于方法区(元空间),对象分配在堆内存,二者通过对象头中的类型指针动态关联;类是静态蓝图,不占堆空间,对象是独立实例,每次new均分配新内存并初始化。

类是抽象模板,对象是具体实例;它们在JVM中通过实例化建立纽带——类定义结构,对象占据堆内存,而类本身存于方法区(元空间),二者靠new指令与内存分配机制动态关联。
类:静态蓝图,不占堆内存
类在编译后生成.class文件,加载进JVM时存入**方法区(Java 8+为元空间)**,只保存结构信息:字段名、方法签名、常量池、访问标志等。它不存储具体数据,也不随new调用而复制——就像建筑图纸,印一份就够了,不会因为盖了十栋楼就变出十份图纸。
- 类的静态变量(
static字段)也存在方法区,被所有实例共享 - 类的方法字节码只加载一次,所有对象调用同一份代码逻辑
- 类本身不是“东西”,不能被赋值或修改状态,它只是运行时的元数据描述
对象:堆中实体,每次new都独立分配
执行new Person()时,JVM在**堆内存**中划出一块连续空间,填入该实例独有的字段值(如name="张三"、age=25),并隐式关联其所属类的元数据地址(存于对象头)。每个对象彼此隔离,改p1.name绝不影响p2.name。
- 对象内存布局包含:对象头(哈希码、GC分代年龄、锁状态、类型指针)、实例数据(字段值)、对齐填充
- 类型指针指向方法区中的类元数据,这是对象能调用类方法的根本依据
- 构造方法执行属于对象初始化阶段,负责给字段赋初始值(默认值或显式设定)
实例化:JVM内部的三步纽带动作
实例化不是“复制类”,而是JVM协调类元数据与堆空间的一次运行时协作:
- 检查类是否已加载:若未加载,先触发类加载子系统(加载→验证→准备→解析→初始化)
-
分配堆内存:根据类中实例字段计算大小,在Eden区(或TLAB)划分空间;零值初始化(如
int→0,Object→null) -
设置对象头 & 执行
<init></init>:写入类型指针、Mark Word;然后调用构造方法,完成用户定义的初始化逻辑
为什么说类和对象是“不同空间、同一纽带”?
类在方法区,对象在堆,看似分离,但JVM靠**对象头里的类型指针**把两者牢牢绑定。这个指针让对象能准确找到自己的类定义,从而调用正确的方法、识别字段偏移量、支持多态分派。没有它,p.toString()就不知道该执行哪个toString——是Person的,还是继承自Object的。
这种设计兼顾了效率(方法复用、类信息集中管理)与灵活性(每个对象状态独立、可动态创建销毁),是JVM面向对象语义落地的核心支撑。











