news 2026/4/15 11:00:38

JVM篇1:java的内存结构 + 对象分配理解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JVM篇1:java的内存结构 + 对象分配理解

JVM 内存结构 + 对象分配详解(HotSpot 虚拟机,JDK 8 ~ 21+ 主流版本)

下面内容基于 HotSpot JVM(Oracle/OpenJDK 默认实现),2025–2026 年主流生产环境基本没有大变化(PermGen 已彻底移除,Metaspace 仍是常态)。

一、JVM 运行时数据区整体划分(线程共享 vs 线程私有)

JVM 内存主要分为以下几个逻辑区域:

区域名称是否线程共享生命周期主要存储内容可能抛出的 OOM 异常是否会 GC
程序计数器 (PC Register)私有线程生命周期当前线程执行的字节码指令地址(分支、循环、异常跳转等)几乎不会 OOM
Java 虚拟机栈 (VM Stack)私有线程生命周期栈帧(局部变量表、操作数栈、动态链接、方法出口等)StackOverflowError / OOM
本地方法栈 (Native Method Stack)私有线程生命周期native 方法(JNI 调用 C/C++)的栈帧StackOverflowError / OOM
Java 堆 (Heap)共享JVM 启动 ~ 关闭几乎所有对象实例、数组OutOfMemoryError: Java heap space是(重点 GC 区域)
元空间 (Metaspace)共享JVM 启动 ~ 关闭类元数据、方法字节码、常量池、符号引用、注解等OutOfMemoryError: Metaspace是(Full GC 时可能回收)
直接内存 (Direct Memory)NIO ByteBuffer.allocateDirect() 分配的 off-heap 内存OutOfMemoryError: Direct buffer memory否(手动或 GC 间接回收)

最核心一句话记忆

二、HotSpot JVM 堆内存详细布局(分代 + G1 时代主流视图)

现代 HotSpot(JDK 8+)默认使用分代思想,但具体收集器不同,物理布局有差异。

1. 最经典的分代布局(Parallel / CMS 时代常见)
Heap ├── Young Generation(新生代) ≈ 1/3 heap │ ├── Eden(伊甸园) ≈ 8/10 young │ └── Survivor(幸存者区)×2 From / To 各 ≈ 1/10 young └── Old Generation(老年代 / 养老区) ≈ 2/3 heap
2. G1 收集器时代(JDK 9+ 默认,2025–2026 生产主流)

G1 已经取消严格的连续 Young/Old 区域,而是把整个堆切成很多个Region(默认 2048 个,可调):

G1 内存布局示意(逻辑分代,物理碎片化):

Heap → 很多个 Region(大小相等) ┌───────────────┐ │ Eden Regions │ ├───────────────┤ │ Survivor Regs │ ├───────────────┤ │ Old Regions │ ├───────────────┤ │ Humongous Reg │ ← 大对象专用 └───────────────┘

三、Java 对象创建 & 内存分配全过程(面试高频)

new 对象时 JVM 做了什么?(8 个步骤)

  1. 类加载检查
    遇到 new 指令 → 先检查常量池中是否有该类的符号引用 → 如果没有则触发类加载(加载 → 链接 → 初始化)

  2. 分配内存(核心步骤)
    在堆中划出一块确定大小的内存给对象(对象大小在类加载后已知)。

    分配方式两种(取决于堆是否规整):

    方式适用收集器堆是否规整原理并发安全解决方案
    指针碰撞Serial / ParNew指针向空闲端移动 size 距离TLAB(线程本地分配缓冲)
    空闲列表CMS / G1(部分情况)从空闲列表中找一块足够大的空间CAS + 失败重试

    TLAB(Thread Local Allocation Buffer)是 HotSpot 解决并发分配的优化:

  3. 初始化零值
    分配的内存空间(对象头除外)全部置为零值(保证字段不赋初值也能用)

  4. 设置对象头

  5. 执行 方法(构造器)
    按照代码顺序执行父类构造 → 成员变量显式赋值 → 构造代码块 → 构造方法体

四、对象分配的“特殊规则”(面试加分项)

  1. 大对象直接进老年代
    -XX:PretenureSizeThreshold=(默认 0)
    大于这个值的对象直接分配到老年代(避免在 Survivor 来回复制)

  2. 动态年龄判定(Survivor 区晋升老年代规则)
    如果 Survivor 空间中相同年龄的所有对象大小总和 > Survivor 空间的一半(默认 50%,-XX:TargetSurvivorRatio),年龄 >= 该年龄的对象直接晋升老年代

  3. 长期存活的对象进入老年代
    默认经历 15 次 Minor GC 后晋升(-XX:MaxTenuringThreshold=15)

  4. 空间分配担保
    Minor GC 前,老年代最大可用连续空间 < 新生代所有对象总大小 → 提前 Full GC

五、快速记忆口诀(面试背诵版)

内存结构口诀
“程栈本堆元,私私私共共”
程序计数器、虚拟机栈、本地方法栈(私有)
堆、元空间(共享)

堆内布局口诀(分代时代):
“新生伊甸幸存俩,老年养老养老家”

对象分配口诀
“先查类加载 → 指针碰撞或空闲列表 → TLAB 加速 → 零值填充 → 对象头 → 构造执行”

晋升老年代三板斧
大 → 直接老
老 → 年龄阈值(默认 15)
多 → 动态年龄判定(同龄 > Survivor/2)

希望这篇能让你对 JVM 内存结构 + 对象分配有清晰的整体认知。
下一期想看哪个方向?

随时告诉我!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/14 5:20:06

cursor JBPM 7+

cursor JBPM 7 集成工作流方面表现一般啊&#xff0c;弄不出来啊。投喂数据项目不够&#xff0c;构建系统框架还是不够给力&#xff0c;因为复杂度高&#xff0c;熟练度&#xff0c;逻辑太多。 这个是我们老早就做的OAMS系统 OAMS 办公自动化 AI犯错误表现&#xff0c;因此需要…

作者头像 李华
网站建设 2026/4/13 10:58:07

Cute_Animal_For_Kids_Qwen_Image用户体验报告:教师与家长反馈分析

Cute_Animal_For_Kids_Qwen_Image用户体验报告&#xff1a;教师与家长反馈分析 1. 项目背景与核心功能 Cute_Animal_For_Kids_Qwen_Image 是基于阿里通义千问大模型开发的专用图像生成工具&#xff0c;专注于为儿童教育和家庭互动场景提供高质量、风格统一的可爱动物图片。该…

作者头像 李华
网站建设 2026/4/10 15:47:55

Qwen1.5-0.5B热更新机制:模型无缝切换部署方案

Qwen1.5-0.5B热更新机制&#xff1a;模型无缝切换部署方案 1. 背景与目标&#xff1a;轻量级AI服务的现实挑战 在边缘设备和资源受限环境中&#xff0c;部署大语言模型&#xff08;LLM&#xff09;一直是个难题。传统做法是为不同任务加载多个专用模型——比如用BERT做情感分…

作者头像 李华
网站建设 2026/4/12 17:45:20

FLOW LAUNCHER vs 传统开发:效率提升300%的秘密

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个效率对比工具&#xff0c;展示FLOW LAUNCHER与传统手动开发在时间、代码量和错误率上的差异。工具应包含一个计时器、代码行数统计和错误检测模块&#xff0c;生成可视化报…

作者头像 李华
网站建设 2026/4/13 19:34:22

效率对比:传统OpenSSL vs 现代工具生成SSL证书

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个可视化SSL证书生成器&#xff0c;左侧展示传统OpenSSL需要执行的7步命令行操作&#xff0c;右侧提供对应功能的图形化按钮&#xff08;如一键生成密钥对&#xff09;。每次…

作者头像 李华