当前位置: 首页 > news >正文

【JVM】JVM的内存结构是怎样的?

JVM的内存结构是Java程序运行时内存管理的核心,不同区域有明确的职责。

一、整体划分

包括两大部分,分为线程私有区域(随线程创建/销毁,无需垃圾回收)和线程共享区域(所有线程共用,需要垃圾回收管理)。

  • 线程私有区域:程序计数器、虚拟机栈、本地方法栈。 支撑线程独立执行(如方法调用、指令跟踪)
  • 线程共享区域:堆、方法区(元空间)。 存储对象实例、类信息等全局数据,是内存管理的核心区域

二、各区域详解:

1.程序计数器(Program Counter Register):

  • 线程私有: 每个线程都有独立的程序计数器,互不干扰。
  • 作用:记录当当前线程 “下一条要执行的 JVM 字节码指令的地址”,为线程提供执行路标,确保线程在切换(如CPU调度被中断)后能够恢复到正确的执行位置。

若执行的是 Java 方法,计数器存储下一条要执行的字节码指令的地址;
若执行的是 Native 方法(本地方法,如 C/C++ 实现),计数器值为undefined。 因为Native方法的执行由操作系统控制,而非JVM,无需JVM记录指令地址。

特点:
1.内存空间极小,几乎不占用资源。
2.是JVM中唯一不会发生OutOfMemoryError(OOM) 的区域
3.本质是线程执行的路标,确保线程切换(如CPU调度)后能恢复到正确执行的位置。

2.虚拟机栈:

  • 线程私有:每个线程创建时,会分配一个虚拟机栈生命周期与线程一致。
  • 作用:记录方法调用的执行状态,每个方法调用时,会创建一个栈帧,栈帧入栈;方法执行完毕,栈帧出栈。
  • 栈帧包含的内容:
    1.局部变量表: 存储方法内的局部变量(如基本类型、对象引用),容量在编译期确定;
    2.操作数栈:方法执行时的临时数据存储区(如计算a+b时,先将a和b入栈,再执行加法);
    3.动态链接:指向方法区中该方法的符号引用(运行时转换为直接引用)
    4.返回地址:方法执行完后,回到调用者的位置(如main方法调用func(),func()执行完需回到main的下一行)。

可能的异常:
1.StackOverflowError:线程请求的栈深度超过虚拟机允许的最大深度(如递归调用无终止条件);
2.OutOfMemoryError:虚拟机栈可动态扩展时,扩展失败(如创建过多线程,栈内存总需求超过系统内存)。

3.本地方法栈:

  • 线程私有:与虚拟机栈功能类似,但专门为 Native 方法(非 Java 实现的方法)服务。
  • 特点:
    可能抛出StackOverflowError(栈深度超限)和OutOfMemoryError(内存不足),与虚拟机栈一致。

4.堆:

  • 线程共享:JVM中内存占比最大的区域,几乎所有对象实例(包括数组)都在这里分配内存。
  • 作用存储对象实例,是**垃圾回收(GC)**的主要工作区域。
  • 结构划分:
    堆空间通常按照对象“存活时间”划分为以下区域:
    • 新生代:存放新创建的对象,分为:
      • Eden区(伊甸园):新对象优先分配到这里。
      • Survivor 区(幸存者区):分为 From 和 To 两个大小相等的区域,用于存放 Eden 区回收后存活的对象(每次 GC 后,存活对象在 From 和 To 之间转移,经过多次存活后进入老年代)。
    • 老年代:存放存活时间长的对象(如经过多次年轻代 GC 仍存活的对象)。

特点:
1.堆的大小可通过**-Xms(初始堆大小)和-Xmx(最大堆大小)参数配置(尽可能两者设为一致,避免动态扩展消耗性能);
2.是
OOM 最常见的区域**(如创建对象过多且无法被 GC 回收,堆空间耗尽时抛出java.lang.OutOfMemoryError: Java heap space)。

5.方法区:

  • 线程共享:存储已被 JVM 加载的类信息、常量、静态变量、即时编译器(JIT)编译后的代码等数据。
  • 历史演进
    • JDK 7 及之前:方法区的实现称为 “永久代(PermGen)”,属于堆的一部分,大小固定(易 OOM);
    • JDK 8 及之后:永久代被元空间(Metaspace) 取代,元空间不再使用堆内存,而是直接使用本地内存(Native Memory),大小受系统内存限制(更灵活)。
  • 运行时常量池
    是方法区的一部分,存放编译期生成的符号引用和字面量(如字符串常量"abc")。

三、各区域的协作关系:

Java 程序运行时,内存流转大致如下:
1.类加载器将类信息加载到方法区(元空间)
2.主线程启动,创建虚拟机栈,main方法的栈帧入栈;
3.执行new Object()时,在中创建对象实例,栈帧的局部变量表存储该对象的引用(地址);
4.程序计数器记录当前执行的字节码指令地址,确保线程切换后能继续执行;
5.方法执行完毕,栈帧出栈;对象不再被引用时,由 GC 在堆中回收。

http://www.xdnf.cn/news/1349569.html

相关文章:

  • mysql为什么使用b+树不使用红黑树
  • Elasticsearch Ruby 客户端 Bulk Scroll Helpers 实战指南
  • TopK问题(堆排序)-- go
  • MySQL存储过程入门
  • 中农具身导航赋能智慧农业!AgriVLN:农业机器人的视觉语言导航
  • PostgreSQL15——查询详解
  • Python 十进制转二进制
  • 【每天一个知识点】AIOps 与自动化管理
  • 使用隧道(Tunnel)连接PostgreSQL数据库(解决防火墙问题)(含Java实现代码)
  • AI实验管理神器:WandB全功能解析
  • 【文献阅读】Advances and Challenges in Large Model Compression: A Survey
  • `strncasecmp` 字符串比较函数
  • Unreal Engine IWYU Include What You Use
  • Vue 插槽(Slots)全解析2
  • ubuntu - 终端工具 KConsole安装
  • AI + 教育:个性化学习如何落地?教师角色转变与技术伦理的双重考验
  • SymPy 中抽象函数的推导与具体函数代入
  • Spring Ai 1.0.1中存在的问题:使用MessageChatMemoryAdvisor导致System未被正确的放在首位
  • c++最新进展
  • fdisk工具源码编译生成
  • DAY14-新世纪DL(DeepLearning/深度学习)战士:破(优化算法)2
  • 多线程下为什么用ConcurrentHashMap而不是HashMap
  • 【Android】 连接wifi时,强制应用使用流量
  • 【从零开始java学习|第九篇】方法的相关知识与练习
  • 【微服务的数据一致性分发问题】究极解决方案
  • 日志的配置
  • 一键部署openGauss6.0.2轻量版单节点
  • Spring原理
  • 最近 | 黄淮教务 | 小工具合集
  • 世界模型一种能够对现实世界环境进行仿真,并基于文本、图像、视频和运动等输入数据来生成视频、预测未来状态的生成式 AI 模型