堆、栈、方法区(JVM 内存模型) 一、虚拟机栈常简称栈存储内容每个 Java 线程私有线程创建时同步创建线程销毁栈直接释放。 核心存储栈帧每调用一个方法就压入一个栈帧方法执行完毕栈帧出栈。 栈帧包含局部变量表基本数据类型、对象引用、操作数栈、动态链接、方法返回地址。核心特点线程私有不存在并发竞争内存分配连续存取速度极快内存空间固定栈深度超出会抛出StackOverflowError生命周期和线程绑定自动回收无需 GC。举例int a 10;局部变量 a 存放在当前方法栈帧的局部变量表。二、堆Java 堆存储内容JVM 中唯一共享的内存区域所有线程共用是 GC 回收的主要区域。 存放所有对象实例、数组只要 new 出来的对象全部存在堆中。核心特点线程共享多线程并发创建对象会有线程安全问题内存空间大动态分配GC 专门管理这块内存内存不足时抛出OutOfMemoryError内部划分为新生代、老年代分代收集提升 GC 效率。举例User user new User();new 出来的 User 实体对象存堆变量 user 只是一个引用存虚拟机栈。三、方法区元空间 MetaSpaceJDK8 重大改动JDK7 及以前永久代方法区使用堆内存实现容易 OOM。JDK8 及以后元空间MetaSpace直接使用本地内存不再占用堆内存几乎不会溢出。存储内容线程共享区域存放类的静态元数据加载后的 Class 字节码信息类名、字段、方法、接口运行时常量池字符串常量、字面量、符号引用静态变量 static、static 代码块即时编译器 JIT 编译后的代码缓存。核心特点线程共享类加载时写入程序运行全程存在JDK8 元空间使用操作系统本地内存可动态扩容只有类卸载、程序关闭才会释放内存存放静态资源和实例对象完全隔离。举例public static String name 张三;static 变量 name、字符串常量 “张三” 都存放在方法区。Class 类元信息 和 new 实例对象 的核心区别一、先分别说清楚两者是什么1. Class 字节码元信息存在方法区 / 元空间当 JVM 通过类加载器加载User.class文件后会解析字节码把这个类本身的模板信息存到方法区。 存储内容类基础信息类名、父类、实现的所有接口、访问修饰符所有字段模板字段名、类型、修饰符static/final/private不存字段具体值所有方法模板方法名、参数列表、返回值、方法字节码、修饰符常量池、注解、静态变量。简单理解这是一张 User 的图纸、模板只定义有什么属性、有什么方法没有真实数据。2. new User () 实体对象存在 Java 堆执行User user new User()时在堆中开辟一块内存创建类的实例。 存储内容对象头mark word、类型指针指向方法区的 User Class 模板实例字段真实数据每个成员变量的具体值不存在方法副本对象不会存储方法调用方法时会去方法区找 Class 模板里的方法。简单理解按照图纸造出来的真实产品有属于自己的属性数值。二、核心区别对比面试重点表格对比维度加载后的 Class 字节码信息new 出来的 User 实例对象存放位置方法区元空间线程共享Java 堆线程共享本质类的模板 / 定义图纸模板实例化后的真实实体存储内容类结构定义字段模板、方法代码、类名、静态变量无实例属性值对象真实数据实例变量的具体数值、对象头不存储方法数量一个类只会加载一份Class 模板全局唯一可以 new 无数个对象每个独立堆内存生命周期JVM 启动加载类后一直存在直到类卸载、程序关闭对象无任何引用时会被 GC 回收销毁访问方式通过反射 ClassUser获取通过对象引用 user 访问静态资源归属存放 static 静态变量所有对象共用不存放静态变量只存独有的实例变量三、举代码例子直观区分java运行class User{ public static String className 用户类; // 静态变量 → Class模板方法区 private String name; // 字段模板存在Class真实值存在实例 private Integer age; public void sayHi(){} // 方法代码只存在Class模板 }Class 模板方法区存储 User 类名、父类 Object、字段模板 name/age、sayHi 方法字节码、静态变量className用户类。两个实例对象堆内存java运行User u1 new User(); u1.name 张三; u1.age 18; User u2 new User(); u2.name 李四; u2.age 20;u1 堆内存name张三age18u2 堆内存name李四age20 两个对象独立各自存储自己的属性值 调用u1.sayHi()时不会自带方法而是通过对象头的类型指针找到方法区里 User 的 Class 模板执行方法。四、一句话总结面试收尾加分Class 字节码信息是类的通用模板全局只存一份定义类有哪些属性和方法而 new 创建的实例是模板的具象产物每个对象独立保存自身属性值堆中可以创建多个。五、三者核心区分总结面试加分私有 / 共享栈线程私有堆、方法区线程共享。存储数据栈局部变量、对象引用 堆new 出来的实例、数组 方法区Class 类信息、静态变量、常量池。内存回收栈线程销毁自动释放无 GC 堆GC 重点回收区域 方法区仅类卸载时回收。速度栈 方法区 堆。高频面试补充考点局部变量存在栈线程安全对象实例在堆多线程操作会有并发问题引用在栈真实对象在堆栈里的引用指向堆内存地址静态变量不属于对象归属于类因此放在方法区所有对象共享同一份静态变量。