news 2026/7/30 5:30:47

堆、栈、方法区(JVM 内存模型)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
堆、栈、方法区(JVM 内存模型)

一、虚拟机栈(常简称栈)

  1. 存储内容每个 Java 线程私有,线程创建时同步创建,线程销毁栈直接释放。 核心存储栈帧:每调用一个方法就压入一个栈帧,方法执行完毕栈帧出栈。 栈帧包含:局部变量表(基本数据类型、对象引用)、操作数栈、动态链接、方法返回地址。
  2. 核心特点
    • 线程私有,不存在并发竞争;
    • 内存分配连续,存取速度极快;
    • 内存空间固定,栈深度超出会抛出StackOverflowError
    • 生命周期和线程绑定,自动回收,无需 GC。
  3. 举例int a = 10;局部变量 a 存放在当前方法栈帧的局部变量表。

二、堆(Java 堆)

  1. 存储内容JVM 中唯一共享的内存区域,所有线程共用,是 GC 回收的主要区域。 存放所有对象实例、数组,只要 new 出来的对象,全部存在堆中。
  2. 核心特点
    • 线程共享,多线程并发创建对象会有线程安全问题;
    • 内存空间大,动态分配,GC 专门管理这块内存;
    • 内存不足时抛出OutOfMemoryError
    • 内部划分为新生代、老年代,分代收集提升 GC 效率。
  3. 举例User user = new User();new 出来的 User 实体对象存堆,变量 user 只是一个引用,存虚拟机栈。

三、方法区(元空间 MetaSpace,JDK8 重大改动)

JDK7 及以前:永久代

方法区使用堆内存实现,容易 OOM。

JDK8 及以后:元空间(MetaSpace)

直接使用本地内存,不再占用堆内存,几乎不会溢出。

  1. 存储内容线程共享区域,存放类的静态元数据
    • 加载后的 Class 字节码信息(类名、字段、方法、接口);
    • 运行时常量池(字符串常量、字面量、符号引用);
    • 静态变量 static、static 代码块;
    • 即时编译器 JIT 编译后的代码缓存。
  2. 核心特点
    • 线程共享,类加载时写入,程序运行全程存在;
    • JDK8 元空间使用操作系统本地内存,可动态扩容;
    • 只有类卸载、程序关闭才会释放内存;
    • 存放静态资源,和实例对象完全隔离。
  3. 举例public static String name = "张三";static 变量 name、字符串常量 “张三” 都存放在方法区。

Class 类元信息 和 new 实例对象 的核心区别

一、先分别说清楚两者是什么

1. Class 字节码元信息(存在方法区 / 元空间)

当 JVM 通过类加载器加载User.class文件后,会解析字节码,把这个类本身的模板信息存到方法区。 存储内容:

  1. 类基础信息:类名、父类、实现的所有接口、访问修饰符;
  2. 所有字段模板:字段名、类型、修饰符(static/final/private),不存字段具体值
  3. 所有方法模板:方法名、参数列表、返回值、方法字节码、修饰符;
  4. 常量池、注解、静态变量。

简单理解:这是一张 User 的图纸、模板,只定义有什么属性、有什么方法,没有真实数据。

2. new User () 实体对象(存在 Java 堆)

执行User user = new User()时,在堆中开辟一块内存,创建类的实例。 存储内容:

  1. 对象头:mark word、类型指针(指向方法区的 User Class 模板);
  2. 实例字段真实数据:每个成员变量的具体值
  3. 不存在方法副本:对象不会存储方法,调用方法时会去方法区找 Class 模板里的方法。

简单理解:按照图纸造出来的真实产品,有属于自己的属性数值。

二、核心区别对比(面试重点)

表格

对比维度加载后的 Class 字节码信息new 出来的 User 实例对象
存放位置方法区(元空间),线程共享Java 堆,线程共享
本质类的模板 / 定义图纸模板实例化后的真实实体
存储内容类结构定义:字段模板、方法代码、类名、静态变量;无实例属性值对象真实数据:实例变量的具体数值、对象头;不存储方法
数量一个类只会加载一份Class 模板,全局唯一可以 new 无数个对象,每个独立堆内存
生命周期JVM 启动加载类后一直存在,直到类卸载、程序关闭对象无任何引用时,会被 GC 回收销毁
访问方式通过反射 Class<User>获取通过对象引用 user 访问
静态资源归属存放 static 静态变量,所有对象共用不存放静态变量,只存独有的实例变量

三、举代码例子直观区分

java

运行

class User{ public static String className = "用户类"; // 静态变量 → Class模板(方法区) private String name; // 字段模板存在Class,真实值存在实例 private Integer age; public void sayHi(){} // 方法代码只存在Class模板 }
  1. Class 模板(方法区)存储: User 类名、父类 Object、字段模板 name/age、sayHi 方法字节码、静态变量className="用户类"
  2. 两个实例对象(堆内存):

java

运行

User u1 = new User(); u1.name = "张三"; u1.age = 18; User u2 = new User(); u2.name = "李四"; u2.age = 20;
  • u1 堆内存:name="张三",age=18;
  • u2 堆内存:name="李四",age=20; 两个对象独立,各自存储自己的属性值; 调用u1.sayHi()时,不会自带方法,而是通过对象头的类型指针,找到方法区里 User 的 Class 模板执行方法。

四、一句话总结(面试收尾加分)

Class 字节码信息是类的通用模板,全局只存一份,定义类有哪些属性和方法;而 new 创建的实例是模板的具象产物,每个对象独立保存自身属性值,堆中可以创建多个。

五、三者核心区分总结(面试加分)

  1. 私有 / 共享栈:线程私有;堆、方法区:线程共享。
  2. 存储数据栈:局部变量、对象引用; 堆:new 出来的实例、数组; 方法区:Class 类信息、静态变量、常量池。
  3. 内存回收栈:线程销毁自动释放,无 GC; 堆:GC 重点回收区域; 方法区:仅类卸载时回收。
  4. 速度栈 > 方法区 > 堆。

高频面试补充考点

  1. 局部变量存在栈,线程安全;对象实例在堆,多线程操作会有并发问题;
  2. 引用在栈,真实对象在堆,栈里的引用指向堆内存地址;
  3. 静态变量不属于对象,归属于类,因此放在方法区,所有对象共享同一份静态变量。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/30 5:30:41

震惊!这家工厂专产低价冲击试验机,背后秘密令人炸锅!

在工业检测设备领域&#xff0c;冲击试验机作为评估材料抗冲击性能的关键仪器&#xff0c;其市场准入门槛和价格差异巨大。近期&#xff0c;市场上涌现出一些主打“极致低价”的冲击试验机产品&#xff0c;吸引了不少预算有限的用户目光。然而&#xff0c;低价背后往往隐藏着技…

作者头像 李华
网站建设 2026/7/30 5:29:30

【系列:CCG Crypto CrackMe 逆向全解析 · 第 1 篇】

导读&#xff1a; 2001 年&#xff0c;CCG&#xff08;China Cracking Group&#xff09;的 Blowfish 放出了一个 CrackMe&#xff0c;声称"本题多解"。这个系列将完整记录破解它的全过程——从最基础的字节解析&#xff0c;到自定义壳的算法复原&#xff0c;到最后跑…

作者头像 李华
网站建设 2026/7/30 5:28:41

本地代码大模型评测实战(五):公平对比的5个陷阱

模型评测方法论&#xff1a;公平对比的5个陷阱 系列目录 篇1: 模型选型 篇2: 评测框架 篇3: 数据挖掘的13个发现 篇4: 8个坑和1个崩溃 篇5: 公平对比的5个陷阱 ← 当前 你以为在选模型&#xff0c;其实在选评测方法。方法论的偏差&#xff0c;比模型之间的差距更大。 榜单第一名…

作者头像 李华
网站建设 2026/7/30 5:22:10

庞加莱回归定理:宇宙循环的数学基础与物理意义

你是否曾想过&#xff0c;如果时间足够长&#xff0c;宇宙中的一切会不会精确地重复发生&#xff1f;你此刻阅读这篇文章的瞬间&#xff0c;会不会在未来的某个时刻再次出现&#xff1f;这个看似科幻的问题&#xff0c;其实在数学和物理学中有一个严谨的理论基础——庞加莱回归…

作者头像 李华
网站建设 2026/7/30 5:10:18

Altium Designer Gerber文件生成全流程详解与实战技巧

1. 项目概述&#xff1a;为什么Gerber文件是PCB制造的“普通话”在电子硬件开发领域&#xff0c;完成一块PCB的设计只是万里长征的第一步。当你把精心绘制的.PcbDoc文件发给板厂&#xff0c;得到的回复很可能是&#xff1a;“请提供Gerber文件。”对于很多刚接触Altium Designe…

作者头像 李华