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

JVM 内存分区

目录

  • 一、JVM内存分区
    • 1.程序计数器
    • 2.栈
    • 3.堆
    • 4.方法区(元空间)
    • 5.字符串常量池
  • 二、对象创建过程
    • 1.类加载检查
    • 2.分配内存
    • 3.初始化0值
    • 4.设置对象头
    • 5.执行init()方法(构造方法)

一、JVM内存分区

Java虚拟机(Java Virtual Machine, JVM)是在运行阶段执行Java字节码(.class)的虚拟操作系统。引入JVM是为了实现了对象内存的自动分配和回收,不用向C++一样手动分配和回收内存,编码更简单,但有得有失,由于引入了JVM,编译阶段无法直接编译成指令序列,而是运行阶段实时编译,运行速度相较于编译型语言慢。

JVM在运行过程中会把它管理的内存划分成若干个不同的数据区域:

1.程序计数器

CPU对于指令是顺序执行的,每次读取内存空间中的一部分数据(指令)执行,程序计数器就是下一条要执行的指令的内存地址,所以每个线程(CPU)都有自己的程序计数器。

线程之间的切换可能当前线程并未执行完,那么就要保存程序计数器的内容,等到线程再次获得CPU后恢复程序计数器现场,实现线程从上次中断的位置继续执行

2.栈

当调用start()方法时开启新的线程,JVM就会为新的线程分配独立栈空间,并在栈空间中执行run()方法。当run()方法执行完毕,线程被销毁时栈空间也会被释放

Java 线程

每一次方法调用都会有一个对应的栈帧被压入栈中,每一个方法执行完(正常/异常)栈帧被弹出,每个栈帧中都拥有:

  • 局部变量表:存放数据、对象引用。
  • 操作数栈:用于存放方法执行过程中产生的中间计算结果、临时变量。
  • 动态链接:首先需要明确,所有方法都保存在方法区中,而要调用这些方法,就需要拿到方法在常量池中的符号引用才能定位到方法区的方法代码执行,由于多态的存在(父类引用指向一个子类对象),编译阶段javac无法确定引用执行的是父类的方法还是子类的方法,就需要动态链接确认要执行的方法并指向常量池中的符号引用。

3.堆

堆是所有线程共享的一块内存区域,用于存放对象实例,因此是垃圾回收器管理的主要区域。


堆又细分为多个空间,目的是更有效的分配和回收内存。默认首先在Eden为对象分配空间,在垃圾回收器执行后,如果该对象还存在那么将对象转移到S0、S1,当对象用于记录年龄的4bit=1111时会进入Tenured

4.方法区(元空间)

线程共享的内存区域,JVM加载类时会从Class文件中解析类的结果、每个方法的指令序列存储到方法区。同时在字符串常量池中保存每个类、每个方法的符号引用。

5.字符串常量池

字符串常量池位于堆空间中,是JVM为了减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免引用类型String对象的重复创建。

  • 每一个唯一字符串会在常量池中创建对应的对象,堆中String对象存储常量池中对象的内存地址,并返回给引用
  • String s1="abcdef";直接将常量池中的字符串对象赋值给当前引用,不会再堆中实例化额外对象,如果常量池中没有"abcdef"则会在常量池中创建字符串对象。
  • String s2 = new String("xy");首先在堆空间实例化对象并指向常量池中的对象,然后返回给当前引用,如果常量池中没有"xy"则会在常量池中创建新的字符串对象。

以下代码创建了几个对象?

String s1 = new String("abc"); String s2 = new String("abc");

答案:3个。字符串常量池中创建一个“abc”, 堆内存中有两个String 对象。

二、对象创建过程

1.类加载检查

虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中找到符号引用,并且检查这个符号引用代表的类是否已加载到方法区,如果没有,那必须先执行相应的类加载过程。

2.分配内存

类加载后,JVM从堆中划分一块内存空间给当前对象。分配方式有两种:

  • 指针碰撞:已分配的内存全部整合到一边,空闲内存放在另一边,中间有一个分界指针,向空闲内存方向移动指针即可划分一块内存空间
  • 空闲列表:JVM维护一个列表,该列表中会记录哪些内存块是可用的,从列表中找一块儿足够大的内存块划分给对象,最后更新列表记录。

内存分配的并发问题:分配内存的过程由于多处理器也会产生并发问题,JVM的思路是首先为每个线程预分配一块堆空间,线程操作自己的堆空间不会有并发问题,当分配的空间不够了,使用CAS+自旋保证内存分配的原子性

3.初始化0值

内存分配完成后,JVM将分配到的内存空间内容都初始化为0,这一步是为了保证将原来使用这片内存空间的对象数据清空,防止脏读

4.设置对象头

JVM对对象进行必要的设置:

  • 标记字段(Mark Word):对象的锁状态标志、线程持有的锁、4bit对象年龄(熬过一次GC年龄+1)。
  • 类型指针(Klass pointer):指向类定义在方法区存放的位置

5.执行init()方法(构造方法)

设置成员变量的初始值。

http://www.jsqmd.com/news/239924/

相关文章:

  • 书匠策AI:颠覆你的课程论文写作体验,从“小白”到“大神”只需一步
  • 统一电能质量变换器(UPQC)Matlab/Simulink仿真:IP-IQ检测与电压电流补偿...
  • 救命神器8个AI论文平台,本科生毕业论文救星!
  • 南芯烧录软件使用
  • 精密的舞步:探秘十字滑台的工业灵魂
  • 制造业企业数据采集系统选型指南:从技术挑战到架构实践
  • 西门子PLC博图与优傲UR机器人的Profinet通讯实战
  • 新手友好的锁相环学习电路:从理论到实践
  • 易语言开发从入门到精通:答疑解惑·踩坑避坑·优化提升·常用资源
  • 【干货收藏】智能体执行一半就终止?大模型上下文窗口超长问题深度解析
  • 梁文锋署名新论文,DeepSeek V4架构首曝?直击Transformer致命缺陷
  • 【开题答辩全过程】以 山河大学奖学金评定系统为例,包含答辩的问题和答案
  • 【必藏】AI Agent完全指南:从ChatGPT到能思考、会行动的智能体革命
  • 径流水土流失监测设备
  • 【开题答辩全过程】以 基于安卓的医疗健康查询系统为例,包含答辩的问题和答案
  • 必藏!一文搞懂Agent开发的三大设计范式:ReAct、Plan Execute与Multi-Agent
  • 人工智能究竟是如何思考的
  • MAC 地址
  • 【开题答辩全过程】以 基于web的拍卖系统设计与实现为例,包含答辩的问题和答案
  • 【开题答辩全过程】以 基于Java的校内美食推荐系统的设计与实现为例,包含答辩的问题和答案
  • 鸿蒙应用的安全审计与合规检测实战:智能待办的安全防护
  • 攻防演练全流程实战指南:红队突破与蓝队防御核心技巧
  • Java实现Html保存为.mhtml文件
  • 3款好玩的台球游戏,玩过的人都说很上头
  • AI Agent企业落地避坑指南:7大致命错误,收藏级干货
  • Google DeepMind :RAG 已死,无限上下文是伪命题?RLM 如何用“代码思维”终结 AI 的记忆焦虑
  • 跨境远控无忧,开启高效跨国连接新时代
  • 语音识别噪声抑制优化实战
  • 8款全场景CRM系统横向对比:从获客闭环到供应链协同的能力矩阵
  • 基于 RPA 的企微外部群自动化架构实现