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

【JVM】内存模型

文章目录

  • 内存模型的基本概念
    • 案例
  • 程序计数器
    • `Java`虚拟机栈
      • 局部变量表
        • 栈帧中局部变量表的实际状态
        • 栈帧中存放的数据有哪些
      • 操作数栈
      • 帧数据
    • 本地方法栈
    • 堆空间是如何进行管理的?
  • 方法区
    • 静态变量存储
  • 直接内存
    • 直接内存的作用

内存模型的基本概念

在前面的学习中,我们知道了字节码文件(.class)会通过类加载器加载JVM虚拟机中,接下来JVM虚拟机就会执行其中的字节码指令.我们把JVM虚拟机被分配的内存叫做运行时数据区域
内存模型就是指运行时数据区域中被划分的不同区域.
JDK6版本:
在这里插入图片描述字符串常量池存放在方法区中,方法区存放在堆中;
JDK1.7版本:
在这里插入图片描述

  • 方法区脱离堆,单独占用一部分内存

  • 字符串常量池依旧存储在堆中
    JDK1.8版本:
    在这里插入图片描述

  • 方法区发生移动,从JVM虚拟机内存中,移动到本地内存中

Java虚拟机(JVM)的内存模型是Java程序运行时内存管理的基础。它定义了Java程序如何在内存中分配、使用和回收资源

案例

class Person{int id;String name;public Person(int id,String name){this.id=id;this.name=name;}
}
public class JvmTest {public void func1(int a){int b=10;Person p=new Person(1,"张三");a=11;}public static void main(String[] args) {int a=10;new JvmTest().func1(a);System.out.println(a);}
}

在这里插入图片描述

程序计数器

  1. 控制程序解释执行指令的顺序.在代码执行过程中,程序计数器会记录下一行字节码指令的地址.执行完当前指令之后,虚拟机的执行引擎根据程序计数器执行下一行指令.程序计数器可以控制程序指令的进行,实现分治,跳转或者异常等等逻辑
  2. 保证在多线程的情况下线程之间的切换.JVM虚拟机需要通过程序计数器记录CPU切换前解释执行到哪一行指令并继续解释运行

程序计数器会不会发生内存溢出?
内存溢出:程序在使用某一块内存区域时,存放的数据需要占用的内存大小超过了虚拟机能够提供的内存上限
程序计数器不会发生内存溢出的情况.原因:每个程序计数器只会存储一个固定长度的内存地址,也就是字节码指令的内存地址.

Java虚拟机栈

保存在java中实现的方法
采用的数据结构来管理方法调用中的基本数据,先进后出,每一个方法的调用使用一个栈帧来保存.
Java虚拟机栈随着线程的创建而创建,随着线程的结束而销毁
在每一个栈帧中,存放的内容有:局部变量表,操作数栈,帧数据
在这里插入图片描述

局部变量表

在方法执行过程中存放所有的局部变量,编译成字节码文件时,就可以确定局部变量表的内容
在这里插入图片描述

栈帧中局部变量表的实际状态

栈帧中的局部变量表是一个数组,数组中的每一个位置称之为,longdouble类型占用两个槽,其他类型占用一个槽.
在这里插入图片描述

栈帧中存放的数据有哪些
  • 实例方法中的序号为0的位置存放的是this,指的是当前调用方法的实例对象,运行时会在内存中存放实例对象的地址
  • 方法参数也会保存在局部变量表中,其顺序与方法中参数定义的顺序一致

局部变量表保存的内容有:

  • 实例方法的this对象
  • 方法的参数
  • 方法体声明的局部变量

为了节省空间,局部变量表中的槽是可以复用的,一旦某个局部变量不再生效,当前槽就可以再次被使用

操作数栈

操作数栈是栈帧中虚拟机执行指令过程中用来存放临时数据的一块区域

  • 操作数栈是栈帧中虚拟机在执行指令的过程中用来存放中间数据的一块区域.他是一种栈式的数据结构,如果一条指令将一个值压入操作数栈,则后面的指令可以弹出并使用该值.

比如:在字节码指令执行的过程中,会产生一些临时数据,这些临时数据会先存放到操作数栈中,然后再通过下一条指令放入到局部变量表中

  • 在编译期就可以确定操作数栈的最大深度,从而执行时正确的分配内存大小

帧数据

(这个并不是由虚拟机设定标准)
帧数据主要包含动态链接,方法出口,异常表引用

  • 动态链接:当前类的字节码指令引用了其他类的属性或者方法时,需要将符号引用(编号)转换成对应的运行时常量池中的内存地址.动态链接就保存了编号到运行时常量池的内存地址的映射关系.
    在这里插入图片描述

  • 方法出口:方法在正确或者异常结束时,当前栈帧会被弹出,同时程序计数器应该指向上一个栈帧中的下一条指令的地址.所以在当前栈帧中,需要存储此方法出口的地址.

  • 异常表:存放的是代码中异常的处理信息,包含了异常捕获的生效范围以及异常发生后跳转到的字节码指令位置.

Java虚拟机栈是否会出现栈内存溢出?

  • Java虚拟机栈如果栈帧过多,占用内存超过栈内存可以分配的最大容量,就会出现栈溢出(虚拟机为每一个线程分配的栈的大小是有限的)
  • Java虚拟机栈内存溢出时会出现StackOverflowError的错误

本地方法栈

保存的是在java中实现的使用native修饰的,实际是由C++编写的本地方法

  • Java虚拟机栈存储了Java方法调用时的栈帧,而本地方法栈存储的是native本地方法的栈帧.
  • HotSpot虚拟机中,Java虚拟机栈和本地方法栈实现上使用了同一个栈空间.本地方法栈在栈内存上生成一个栈帧,临时保存方法的参数同时方便出现异常时也把本地方法的栈信息打印出来.
    在这里插入图片描述

一般Java程序中堆内存是空间最大的一块内存区域.创建出来的对象都存在于堆上
Java 堆是所有线程共享的一块内存,在虚拟机启动时创建,几乎所有的对象实例都存放在这里,是垃圾收集器管理的主要区域
栈上的局部变量表中,可以存放堆上对象的引用.静态变量也可以存放堆对象的引用,通过静态变量就可以实现对象在线程之间的共享.
在这里插入图片描述

堆内存是否会出现溢出?
堆内存大小是有上限的,当对象一直向堆中放入对象达到上限之后,就会抛出OutOfMemory错误

堆空间是如何进行管理的?

堆空间有三个需要关注的值:uesd,total,max

  • used指的是当前已经使用的堆内存;
  • totaljava虚拟机已经分配可用堆内存;
  • maxjava虚拟机可以分配的最大堆的内存
    在这里插入图片描述

随着堆中对象增多,当total可以使用的内存即将不足的时候,虚拟机会继续分配内存给堆,扩展total的大小

  • 如果堆内存不足,java虚拟机就会不断地分配内存,total值会变大.
  • 是不是当used=total=max,就会导致内存溢出?
    答案:不一定

在实际应用中一般都需要设置totalmax的值

  • 要修改堆的大小,可以使用虚拟机参数-Xmx(max最大值)和-Xms(初始的total)
    • 语法:-Xmx值,-Xms
    • 单位:字节(默认,必须是1024倍数),K或者k(KB),m或者M(MB),g或者G(GB)
    • 限制:Xmx必须大于2MB,Xms必须大于1MB

Java服务端程序开发的时候,建议将-Xmx-Xms设置为相同的值(total=max),这样在程序启动之后可使用的总内存就是最大内存,而无需向Java虚拟机再次申请,减少了申请并分配内存时间上的开销,同时也不会出现内存过剩之后堆收缩的情况

方法区

方法区是存放每个类基础信息的位置,线程共享,主要包含三部分内容:

  • 类的元信息:每个类的基本信息
    一般称之为InstanceKlass对象.在类加载阶段完成
    在这里插入图片描述
  • 运行时常量池
    • 常量池中存放的是字节码中的常量池内容
    • 字节码文件中通过编号查表的方式找到常量,这种常量池称之为静态常量池
    • 常量池加载到内存中之后,可以通过内存地址快速的定位到常量池中的内容,这种常量池称之为运行时常量池.
      在这里插入图片描述
    • 字符串常量池:保存了字符串常量
      字符串常量池存储在代码中定义的常量字符串内容.比如:"123",这个123就会被放入字符串常量池
      在这里插入图片描述
      这里我们再来举个例子加深印象:
      举例1:
public class StringTest {public static void main(String[] args) {String a="1";String b="2";String c="12";String d=a+b;System.out.println(c==d);}
}

这里的运行结果就代表了我们的d是存放在字符创常量池中还是堆内存中.
运行结果false,原因如下:
在这里插入图片描述
举例2:

public class StringTest {public static void main(String[] args) {String a="1";String b="2";String c="12";String d="1"+"2";System.out.println(c==d);}
}

运行结果是:true,为什么?
我们来观察一下此时的字节码指令状态:
在这里插入图片描述
所以,此处d存放在常量池中的原因是:这里并没有使用StringBuilder对象来进行字符串的相加,而是直接使用的ldc字节码指令进行的,没有使用对象,所以就不需要存放在

静态变量存储

  • JDK7之前的版本中,静态变量是存放在方法区中的,也就是永久代
  • JDK7及其之后的版本中,静态变量时存放在堆中的Class对象中,脱离了永久代

直接内存

首先我们要确定的是,直接内存并不属于Java运行时的内存区域.
JDK1.4中引入了NIO机制,使用了直接内存,主要为了解决以下两个问题:

  • Java堆中的对象如果不再使用要回收,回收时会影响对象的创建和使用(可能会出现卡顿的现象)
  • IO操作比如读文件,需要先把文件读入直接内存中,再把数据复制到Java堆中.
    现在放入直接放入到直接内存中即可,同时在Java堆上维护直接内存的引用,减少了数据复制的开销.写文件也是这种思路.
    在这里插入图片描述

直接内存的作用

  • 提高读写文件的性能
  • 避免垃圾回收机制影响对象的创建和使用
  • 在`JDK1.78即之后存放方法区

相关文章:

【JVM】内存模型

文章目录 内存模型的基本概念案例 程序计数器栈Java虚拟机栈局部变量表栈帧中局部变量表的实际状态栈帧中存放的数据有哪些 操作数栈帧数据 本地方法栈 堆堆空间是如何进行管理的? 方法区静态变量存储 直接内存直接内存的作用 内存模型的基本概念 在前面的学习中,我们知道了字…...

代码随想录:二叉树的四种遍历

144. 二叉树的前序遍历 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullpt…...

【Linux】从多线程同步到生产者消费者模型:多线程编程实践

目录 1.线程的同步 1.1.为什么需要线程的同步? 2.2.条件变量的接口函数 2.生产消费模型 2.1 什么是生产消费模型 2.2.生产者消费者模型优点 2.3.为何要使用生产者消费者模型 3.基于BlockingQueue的生产者消费者模型 3.1为什么要将if判断变成while&#xff…...

如何在word里面给文字加拼音?

如何在word里面给文字加拼音?在现代社会,阅读已经成为了我们日常生活中不可或缺的一部分。尤其是在学习汉语的过程中,拼音的帮助显得尤为重要。为了帮助大家更好地理解和掌握汉字的发音,许多教师和学生都希望能够在Word文档中为文…...

Detr论文精读

摘要: 作者提到,该方法将物体检测看做直接的集合预测,在传统的目标检测算法中,会先生成候选区域,然后对每个候选区域进行单独的预测(包括物体的分类和预测框的回归),集合预测就是直…...

找寻孤独伤感视频素材的热门资源网站推荐

在抖音上,伤感视频总是能够引起观众的共鸣,很多朋友都在寻找可以下载伤感视频素材的地方。作为一名资深的视频剪辑师,今天我来分享几个提供高清无水印伤感素材的网站,如果你也在苦苦寻找这些素材,不妨看看以下推荐&…...

大模型~合集13

我自己的原文哦~ https://blog.51cto.com/whaosoft/12302606 #TextRCNN、TextCNN、RNN 小小搬运工周末也要学习一下~~虽然和世界没关 但还是地铁上看书吧, 大老勿怪 今天来说一下 文本分类必备经典模型 模型 SOTA!模型资源站收录情况 模型来源论文 RAE ​​ht…...

【Next.js 项目实战系列】04-修改 Issue

原文链接 CSDN 的排版/样式可能有问题,去我的博客查看原文系列吧,觉得有用的话,给我的库点个star,关注一下吧 上一篇【Next.js 项目实战系列】03-查看 Issue 修改 Issue 添加修改 Button​ 本节代码链接 安装 Radix UI 的 Ra…...

【Linux】并行与并发(含时间片)

简单来说 并发:多个进程轮流使用同一个CPU,在逻辑层面上,一段时间内推进完成了多个进程 并行:机器中有多个CPU可以使用,在物理层面上,做到同一时间会有多个进程同时在运行 举个例子:一群人需要…...

【Flutter】页面布局:弹性布局(Flex)

在 Flutter 开发中,布局是非常重要的部分。布局系统允许开发者控制和管理界面上的组件如何排列和展示。弹性布局(Flex)是其中一个非常强大且常用的布局组件,它能够在水平方向或垂直方向上灵活调整子组件的空间分配比例。Row 和 Co…...

深入解析 Go 语言接口:多接口实现与接口组合的实际应用

文章目录 一、引言二、一个类型实现多个接口1. 定义多个接口2. 类型实现多个接口3. 使用多个接口 三、接口的组合1. 接口嵌套2. 实现复合接口 四、实际开发中的应用场景1. 多态与模块化设计2. 松耦合系统设计3. 测试与依赖注入4. 事件驱动架构中的应用 五、小结 一、引言 在 G…...

Eclipse——Java开发详解

Eclipse 1、配置JDK2、设置编译版本2.1、全局编译版本2.2、项目编译版本2.3、Web项目编译版本 3、设置工作目录4、创建Java项目5、配置Tomcat6、创建Web项目7、配置Maven8、创建Maven项目8.1、普通Maven项目8.2、Maven Web项目 9、创建SpringBoot项目10、设置字体11、设置代码提…...

练手小项目推荐

以下是一些练手项目推荐,我可以给你一些适合学生毕业设计的小项目建议,既可以锻炼技能,也能完成学术要求。以下是一些可行的毕业设计项目建议: 校园导航APP 功能:为校园内的新生和访客提供导航,标记教室、…...

一图秒懂色彩空间和色彩模型

色彩空间和色彩模型 想必学过图像处理或者摄影的小伙伴都知道这两个词,看了一些博客,发现很少有人把这两个概念说清楚的,大多数都是混在一起,色彩模型和色彩空间的概念混为一谈,很让人疑惑。   这里我们用一张图来解…...

控制Stable Diffusion生成质量的多种方法

在Stable Diffusion绘图中,控制AI生成图像的质量可以通过多种方法来实现。以下是几种常见的方法: 1. 从底模控制(Checkpoint) 使用不同的模型检查点(Checkpoints)可以显著影响生成图像的质量和细节。选择一…...

递归算法笔记

根据b站视频整理的 **视频地址:**https://www.bilibili.com/video/BV1S24y1p7iH/?spm_id_from333.788.videopod.sections&vd_source6335ddc7b30e1f4510569db5f2506f20 最常见的一个递归例子: 斐波那契数列:1,2,3…...

Android——发送彩信

跳转到相册选择图片 btn_jump.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View view) {// 跳转到系统相册选择图片并返回Intent intent new Intent(Intent.ACTION_GET_CONTENT);// 设置图片类型为图片类型intent.setType("image/*&quo…...

对比迁移项目的改动

文章目录 对比迁移项目的改动场景背景解决方案 对比迁移项目的改动 场景背景 同源定制化项目,同一套代码扩展出来的项目(从领导口中得知) A项目的有三维地图展示,项目B跑起来却加载不出来,但是本地运行A项目代码&…...

数据结构-复杂度

复杂度 1.数据结构1.1算法 2.算法效率2.1复杂度的概念 3.时间复杂度3.1大O渐进表示法3.2时间复杂度计算示例3.2.1 示例13.2.2 示例23.2.3 示例33.2.4 示例43.2.5 示例5:3.2.6 示例63.2.7 示例7 4.空间复杂度4.1.1 示例14.1.2 示例2 5.常见复杂度对比6.复杂度算法题6…...

无人机之放电速率篇

无人机的放电速率是指电池在一定时间内放出其储存电能的能力,这一参数对无人机的飞行时间、性能以及安全性都有重要影响。 一、放电速率的表示方法 放电速率通常用C数来表示。C数越大,表示放电速率越快。例如,一个2C的电池可以在1/2小时内放…...

免费开源AI助手,颠覆你的数字生活体验

Apt Full作为一款开源且完全免费的软件,除了强大的自然语言处理能力,Apt Full还能够对图像和视频进行一系列复杂的AI增强处理,只需简单几步即可实现专业级的效果。 在图像处理方面,Apt Full提供了一套全面的AI工具,包…...

VMware虚拟机三种网络模式详解

主要内容 1. 桥接模式2. NAT模式VMware Network Adapter VMnet8虚拟网卡的作用 3. 仅主机模式VMware Network Adapter VMnet1虚拟网卡的作用设置虚拟机联通外网 4. 总结 参考资料: 1.Vmware虚拟机三种网络模式详解 VMware虚拟机三种网络模式详解之Bridged&#xff0…...

【算法篇】动态规划类(4)——子序列(笔记)

目录 一、Leetcode 题目 1. 最长递增子序列 2. 最长连续递增序列 3. 最长重复子数组 4. 最长公共子序列 5. 不相交的线 6. 最大子序和 7. 判断子序列 8. 不同的子序列 9. 两个字符串的删除操作 10. 编辑距离 11. 回文子串 12. 最长回文子序列 二、动态规划总结 …...

【图解版】力扣第162题:寻找峰值

注意 题目只要求找到一个峰值就可以了。nums[-1]和nums[n]这两个位置是负无穷,也就是说,除了数组的位置之外,其它地方都是负无穷。对于所有有效的 i 都有 nums[i] ! nums[i 1] 方法一 遍历整个数组,找到最高的那个点。时间复杂…...

Windows电脑桌面如何弄个好用的提醒备忘录?

在这个充满挑战的时代,每个人都渴望成为更好的自己。然而,随着生活节奏的加快,我们时常发现自己陷入了各种琐事之中,难以脱身。为了不让重要的事情被遗漏,一款好的提醒备忘录工具就显得尤为关键。那么,Wind…...

Windows API 一 ----起步

目录 1.介绍主函数入口参数。 2. 简单介绍 Windows.h 这个头文件 小结,也聊一聊 1.介绍主函数入口参数。 第一个参数: HINSTANCE 类型的 参数, 称为“实例句柄“,这个参数唯一标志了我们写的这个程序。 第二个参数: HINSTANCE…...

音视频入门基础:H.264专题(19)——FFmpeg源码中,获取avcC封装的H.264码流中每个NALU的长度的实现

一、引言 从《音视频入门基础:H.264专题(18)——AVCDecoderConfigurationRecord简介》中可以知道,avcC跟AnnexB不一样,avcC包装的H.264码流中,每个NALU前面没有起始码。avcC通过在每个NALU前加上NALUnitL…...

【uniapp】设置公共样式,实现公共背景等

目录 1、 全局渐变背景色 2.1 创建common目录 2.2 在common下新建style和images等目录 2.3 在style下新建common-style.scss 2.4 common-style输入全局渐变颜色 2.5 引入样式 2.6 业务页面引入 2.7 展示 2、全局字体颜色 2.1 新建base-style.scss文件 2.2 设置base-…...

Node.js学习笔记

回顾: javascript 可以在浏览器运行 (js代码会JavaScript的解析引擎执行)chrome 》V8 (性能最好)FireFox 》 奥丁猴safri 》JSCoreIE浏览器 》查克拉JavaScript可以在浏览器端操作DOM 和BOM每一个浏览器都内置了B…...

resnetv1骨干

# 普通的卷积残差块 def apply_basic_block( x, filters, kernel_size3, stride1, conv_shortcutTrue, nameNone ): # 预设块名称前缀 if name is None: name f"v1_basic_block_{keras.backend.get_uid(v1_basic_block_)}" # 设置残差连接前…...