news 2026/2/11 12:25:08

HoRain云--深入解析JVM内存模型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HoRain云--深入解析JVM内存模型

🎬 HoRain 云小助手:个人主页

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

目录

⛳️ 推荐

🔧 核心内存区域详解

1. 程序计数器:执行线索的记录者

2. Java 虚拟机栈:方法执行的现场

3. 本地方法栈:Native 方法的支持

4. 堆:对象生存的乐园

5. 方法区:类型信息的仓库

💡 内存管理的演进:从永久代到元空间

🗑️ 垃圾回收与内存模型

💎 总结与实践建议


理解 Java 虚拟机(JVM)内存模型对于编写稳健、高性能的 Java 应用至关重要。它就像是 Java 程序运行的“城市布局”,不同区域承担不同职能,同时又需要高效的“市政管理”(垃圾回收)来保持秩序。下面这张表格汇总了各核心区域的关键信息,帮你快速建立整体认知。

内存区域

线程关系

核心功能

生命周期

异常错误

程序计数器

线程私有

存储当前线程所执行的字节码行号指示器,实现流程控制(分支、循环、跳转等)。

与线程共存亡

Java 虚拟机栈

线程私有

存储方法执行的栈帧,包括局部变量表、操作数栈、动态链接、方法出口信息等 。

与线程共存亡

StackOverflowError(栈深度超限)
OutOfMemoryError(扩展时内存不足)

本地方法栈

线程私有

为虚拟机使用到的 Native 方法服务 。

与线程共存亡

StackOverflowError
OutOfMemoryError

线程共享

存放对象实例和数组,是垃圾回收的主要区域 。

虚拟机启动时创建

OutOfMemoryError(内存不足且无法扩展)

方法区

线程共享

存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等数据 。

虚拟机启动时创建

OutOfMemoryError(内存不足且无法扩展)


🔧 核心内存区域详解

1. 程序计数器:执行线索的记录者

程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器​ 。在多线程环境下,Java 虚拟机通过时间片轮转的方式实现并发执行。当线程切换发生时,程序计数器能确保线程恢复执行时,能知道接下来该执行哪条指令 。执行 Java 方法时,它记录的是虚拟机字节码指令的地址;执行 Native 方法时,其值为空 (Undefined) 。此区域是唯一一个在 Java 虚拟机规范中没有规定任何OutOfMemoryError情况的区域 。

2. Java 虚拟机栈:方法执行的现场

每个方法在执行时,都会在虚拟机栈中创建一个栈帧,用于存储方法运行所需的各种信息 。

当线程请求的栈深度大于虚拟机所允许的深度(例如无限递归),会抛出StackOverflowError。如果虚拟机栈可以动态扩展(大部分虚拟机都可动态扩展),但在扩展时无法申请到足够内存,则会抛出OutOfMemoryError

3. 本地方法栈:Native 方法的支持

本地方法栈与虚拟机栈作用类似,区别在于虚拟机栈为执行 Java 方法服务,而本地方法栈则为虚拟机使用到的 Native 方法服务​ 。HotSpot 虚拟机直接把本地方法栈和虚拟机栈合二为一 。

4. 堆:对象生存的乐园

堆是 Java 虚拟机管理中最大的一块内存区域,被所有线程共享,在虚拟机启动时创建。此区域的唯一目的就是存放对象实例和数组​ 。堆是垃圾收集器管理的主要区域,因此也被称为 “GC 堆” 。从内存回收角度,Java 堆可细分为新生代(Young Generation)和老年代(Old Generation/Tenured Generation),新生代又可细分为 Eden 空间和 Survivor 空间(From Survivor, To Survivor),目的是为了更好地进行内存回收和分配 。

5. 方法区:类型信息的仓库

方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据​ 。方法区是 JVM 规范定义的逻辑部分,具体实现因版本和虚拟机而异。在 JDK 8 之前,HotSpot 虚拟机使用永久代来实现方法区。从 JDK 8 开始,永久代被移除,取而代之的是元空间,它使用本地内存(Native Memory)而非 JVM 内存,从而避免了永久代的内存溢出问题(如java.lang.OutOfMemoryError: PermGen space),其大小仅受本地内存限制 。

运行时常量池是方法区的一部分,用于存放 Class 文件常量池中的符号引用和翻译出来的直接引用,具备动态性(如String.intern()方法可在运行期间将新的常量放入池中)。在 JDK 7 时,字符串常量池已被移至堆中 。


💡 内存管理的演进:从永久代到元空间

特性

永久代(JDK 7 及以前)

元空间(JDK 8 及以后)

实现位置

JVM 堆内存中

本地内存(Native Memory)

内存限制

受 JVM 堆大小参数(如-XX:MaxPermSize)限制

默认仅受本地内存大小限制,可通过-XX:MaxMetaspaceSize设定上限

主要优势

与 JVM 堆统一管理

避免永久代内存溢出提升元数据管理灵活性;利于简化 GC 复杂度

主要挑战

易出现java.lang.OutOfMemoryError: PermGen space;类元信息大小难确定,设置困难

需要关注本地内存使用情况


🗑️ 垃圾回收与内存模型

堆是垃圾收集器工作的主要区域。为了更高效地回收内存,堆被划分为新生代和老年代。


💎 总结与实践建议

  1. 理解核心分区:牢记程序计数器、虚拟机栈、本地方法栈、堆和方法区这五大核心区域及其线程属性、功能和异常。

  2. 关注版本演进:理解 JDK 8 中方法区从永久代到元空间的转变及其意义,这有助于避免配置错误和内存溢出。

  3. 善用 JVM 参数:根据应用特点合理设置堆大小(-Xms,-Xmx)、元空间大小(-XX:MaxMetaspaceSize)、线程栈大小(-Xss)等参数对性能调优至关重要。

  4. 掌握异常诊断:遇到StackOverflowError通常意味着代码中存在过深递归或大量循环调用;而OutOfMemoryError则需分析是堆内存不足、元空间不足还是其他原因。

希望这份详细的解析能帮助你深入理解 JVM 内存模型!如果你对垃圾回收算法的具体细节或性能调优实战有兴趣,我们可以继续深入探讨。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

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

AI专著撰写攻略:精选工具推荐,为你的学术创作添砖加瓦

撰写学术专著不仅考验学术能力,同时也对心理承受力提出了挑战。与团队合作写论文不同,专著的写作通常是孤独的旅程。从选题到构建框架,再到内容的撰写与修改,几乎每一步都需要作者独自面对。长时间的单独创作让研究者难以获得及时…

作者头像 李华
网站建设 2026/2/10 10:45:24

大模型实战项目:基于大模型+知识图谱的知识库问答 (附项目)

今天给大家介绍一个git开源的宝藏项目 — 基于大模型知识图谱的知识库问答,这里还搭配了一个演示dome给大家,如需要此项目练手的,我已经打包好了放在文末~ 基于大模型知识图谱的知识库问答系统 项目整体流程介绍 项目整体包含5个部分&…

作者头像 李华
网站建设 2026/2/10 11:07:19

SEW变频器MCV41A0220-503-4-0T 08275033

SEW变频器MCV41A0220-503-4-0T 08275033技术解析 一、设备基础参数 型号定义 MCV:模块化设计矢量控制变频器41A:400V级三相供电0220:额定功率22kW503-4-0T:软件版本/接口配置代码08275033:序列号(含生产批次…

作者头像 李华
网站建设 2026/2/6 10:10:25

手动加锁解锁版本catch里解锁结果正确分析

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、为什么解开注释后能正常运行?二、手动解锁的隐藏风险(为什么不推荐)1. 风险1:多个退出点导致解锁遗漏2. 风险2&a…

作者头像 李华
网站建设 2026/2/9 8:17:55

AI写专著大揭秘:优质工具推荐,让你轻松完成专业学术著作!

对于学术研究者来说,撰写一本学术专著并不是一瞬间的灵感,而是经历了数年的艰辛努力。从最开始的选题到构建合理的章节架构,再到逐步填充文字和仔细核对文献,每一步都充满了难题。研究者需要在教学与科研之间挤出可用时间&#xf…

作者头像 李华