JVM内存模型介绍
内存模型
内存模型如下图所示
堆
堆是Java虚拟机所管理的内存最大一块。堆是所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域唯一的目的就是存放对象实例。所有的对象实例都在这里分配内存
Java堆是垃圾收集器管理的主要区域。从内存回收的角度来看,由于现在的垃圾收集器采用的是分代收集算法。所以,java堆又分为新生代和老年代。从内存分配的角度来说,线程共享的java对中可能划分出多个线程私有的fenp缓冲区(Thread Local Allocation Buffer)。
可以通过 -Xms、-Xmx分别控制堆初始化是最小堆内存和最大堆内存大小。
虚拟机栈
与程序计数器一样,java虚拟机栈也是线程私有的,他的生命周期与线程相同。
虚拟机栈描述的是Java方法的执行的内存模型:每个方法在执行的同时会创建一个栈桢(stack frame)用于存储局部变量表、操作数栈、动态链表、方法出口等信息。每个方法从调用直至执行完成的过程,就对应着栈桢在虚拟机栈中入栈到出栈的过程。
虚拟机栈存储的数据类型
局部变量表
存放的是编译器可知得到各种基本数据类型boolean、byte、char、short、int、float、long、double、对象引用(refrence类型,不等同于对象本身,一个指向对象的起始内存位置的引用指针)
操作数栈
动态链表
方法出口
...
常见异常
在虚拟机规范中,对这个区域规定了两种异常情况:
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError
如果虚拟机栈可以动态扩展,扩展时无法申请做够的内存,将会爬出OutOfMemorryError
本地方法栈
与虚拟机栈发挥的作用非常类似,他们之间的区别是虚拟机栈为虚拟机执行java方法服务,而本地方法栈则为虚拟机使用到的native方法服务。与虚拟机栈一样,本地房发展区域也会抛出StackOverflowError,OutOfMemorryError异常。
方法区(1.8后该区域被废弃)
方法区与java堆一样,是各个线程所共享的,它用来存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。
方法区是jvm提出的规范,而永久代就是方法区的具体实现。
java虚拟机对方法区的限制非常宽松,可以像堆一样不需要连续的内存可可选择的固定大小外,还可以选择不识闲垃圾收集,相对而言,垃圾收集行为在这边区域是比较少出现的。
在方法区会报出 永久代内存溢出的错误。而java1.8为了解决这个问题,就提出了meta space(元空间)的概念,就是为了解决永久代内存溢出的情况,一般来说,在不指定 meta space大小的情况下,虚拟机方法区内存大小就是宿主主机的内存大小
程序计数器
程序计数器是一块较小的内存空间,他可以看做是当前线程所执行字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选择下一条将要执行的字节码指令。
由于JAVA虚拟机的多线程是通过多线程流转切换并分配处理器执行时间的方式来实现的。在任一一个确定的时刻,一个处理器都只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各个线程的计数器之间互不影响,独立存储,我们称该类内存区域为线程私有
如果线程正在执行一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址。
运行时常量池
运行时常量池是方法区的一部分。Class文件除了 有类的版本、字段、方法、接口等描述信息外,还有一项是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容在类加载后进入方法区的运行时常量池。
运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性.Java语言并不要求常量一定只有在编译器才能产生,依旧是并非预置入Class文件中的常量池的内容才能进入方法区运行时常量池
对象创建
在语言层面上,创建对象(克隆,反序列化)通常只是一个new关键字。
过程
虚拟机在遇到一条new指令时,首先去检查这个指令的参数是否能在常量池中定位到这个类的符号引用并且减产这个符号引用代表的类是否已经被加载、解析、和初始化国。如果没有,那必须执行相应的类加载过程。
在类加载检查通过后,接下来虚拟机将为新生的对象分配内存。对象所需内存的大小在类加载完成后便可完全确定。
内存分配
为对象分配空间的任务等同于把一块确定大小的内存从java堆中划分出来。假设java堆中内存是绝对规整的,所有用过的内存都放在一边,空闲的放在另外一边,中间放着一个指针最为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲的空间那边挪动一段与对象大小相等的距离,这种分配方式称为指针碰撞。
如果内存不是规整的,已使用的和空闲的内存区域是相互交错的,虚拟机必须维护一个列表,记录哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新这个列表。这种分配方式是空闲列表。
选择哪种分配分配方式是由java堆是否规整来决定的,而java堆是否规整又是由其所采用 的垃圾收集器是否带有压缩规整的功能决定,因此,使用Serial、ParNew等带来Compat过程的收集器时,分配算法是指针碰撞。而使用CMS这种基于Mark-Swaeep算法,采用的是空闲列表分配方式。
对象的内存布局
在HotSpot虚拟机中,对象在内存中的存储布局分为3块区域:对象头(Header)、实例数据(Instance Data)、对其补充(Padding)
对象头(Heading)
对象头包括两部分信息
用于存储对象自身运行时数据。
如哈希码,GC分代年龄、锁状态标志、偏向线程ID。这部分s数据的长度在32位和64位的虚拟机中分别为32bit和64bit。
对象的访问定位
创建对象时为了使用对象,java程序需要通过栈上的refrence数据来操作堆上的具体对象。由于refrence类在java虚拟机值规定了一个指向对象的引用,并没有定义这个引用应该通过何种方式去定位、访问堆中的具体位置,所以对象访问方式也取决于虚拟机对这个refrence的具体实现,目前主流的访问凡是是使用句柄、直接指针两种。
句柄访问
如果使用句柄访问的话,那么java堆中就会划分出一块内存来座位句柄池,refrence中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据的各自具体的地址信息。
指针直接访问
如果使用指针直接访问,那么java堆对象的布局就必须考虑如何放置访问类型数据的相关信息,而refrence中存储的直接就是对象地址
这个两种访问方式各有优势,使用句柄访问的最大好处就是refrence中存储的是稳定的句柄地址,在对象被移动(垃圾收集时)只会改变句柄中对象实例指针,refrence本省不需要修改。
使用直接指针访问的方式最大的好处就是速度更快,节省了一次指针定位的事件开销。由于对象的访问在java中非常频繁,一次这类开销积少成多也是一个比较客观的优化。
相关文章:
JVM内存模型介绍
内存模型 内存模型如下图所示 堆 堆是Java虚拟机所管理的内存最大一块。堆是所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域唯一的目的就是存放对象实例。所有的对象实例都在这里分配内存 Java堆是垃圾收集器管理的主要区域。从内存回收的角度来看&am…...
2000-2021年地级市产业升级、产业结构高级化面板数据
2000-2021年地级市产业升级、产业结构高级化面板数据 1、时间:2000-2021年 2、范围:地级市 3、指标:年份、地区、行政区划代码、地区、所属省份、地区生产总值、第一产业增加值、第二产业增加值、第三产业增加值、第一产业占GDP比重、第二…...
Java实现密码加密实现步骤【bcrypt算法】
一、SpringBoot和SSM框架均可实现密码加密的方法 在Spring Boot和SSM中实现密码加密可以使用bcrypt算法。bcrypt是一种密码哈希函数,通过将密码与随机生成的盐值进行混合,然后再进行多次迭代的计算,最终生成一个安全的哈希密码。 下面是使用…...
商城-学习整理-集群-K8S(二十三)
目录 一、k8s 集群部署1、k8s 快速入门1)、简介2)、架构1、整体主从方式2、Master 节点架构3、Node 节点架构 3)、概念4)、快速体验1、安装 minikube2、体验 nginx 部署升级 5)、流程叙述 2、k8s 集群安装1、kubeadm2、…...
MATLAB算法实战应用案例精讲-【深度学习】强化学习
目录 基础知识点 马尔科夫决策过程 策略梯度定理 蒙特卡洛策略梯度定理 REINFORCE 算法...
时间和日期--Python
1. 时间:time模块 总结:2. datetime模块 相比与time模块,datetime模块的接口更直观、更容易调用 2.1 datetime模块定义的类 (1)datetime.date:表示日期的类。常用的属性有:year、month、day; ÿ…...
【Git】学习总结
【Git】学习总结 【一】安装【二】Git克隆项目代码【1】idea下载git项目【2】创建新的分支【3】新建的分支推送到远程【4】合并最新代码到主分支【5】切换分支 【三】提交本地项目到远程🚀1. 配置 Git🚀2. 创建项目远程仓库🚀3. 初始化本地仓…...
手写Spring源码——实现一个简单的spring framework
这篇文章主要带大家实现一个简单的Spring框架,包含单例、多例bean的获取,依赖注入、懒加载等功能。文章内容会持续更新,感兴趣的小伙伴可以持续关注一下。 目录 一、创建Java项目 二、开始实现Spring 1、创建BeanFactory接口 2、创建Appl…...
银河麒麟服务器、centos7服务器一键卸载mysql脚本
脚本 # 查看mysql相关的rpm包写到rmsql.sh文件中 rpm -aq | grep -i mysql >rmsql.sh # 修改文件为卸载mysql的脚本文件 sed -i -e s/^/yum remove -y / rmsql.sh # 修改文本权限 chmod 777 rmsql.sh # 全盘查找mysql相关文件,写到my.sh脚本中 find / -name mysq…...
【随笔】- 程序员的40岁后健身计划
【随笔】- 40岁后程序员的健身计划 文章目录 【随笔】- 40岁后程序员的健身计划一、树立健身信心,制订坚持计划二、挑选让你舒适的方式三、调整速度,以间歇式训练为主四、刚开始锻炼,别求太快五、增加力量、柔韧性和平衡练习六、运动多样化七…...
后端项目开发:集成Druid数据源
Druid作为连接池中间件可以监控数据库访问性能,对数据库密码加密,查看SQL执行日志,扩展JDBC。 添加依赖 <!-- druid --> <dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter&…...
深度学习11:Transformer
目录 什么是 Transformer? Encoder Decoder Attention Self-Attention Context-Attention 什么是 Transformer(微软研究院笨笨) RNN和Transformer区别 Universal Transformer和Transformer 区别 什么是 Transformer? …...
免费开源跨平台视频下载器 支持数百站点视频和音频下载-ytDownloader
ytDownloader: ytDownloader是一款免费开源跨平台视频下载器,帮助用户从数百个网站下载不同格式的视频和提取音频,使用简单,复制视频链接粘贴即可下载,支持4K画质视频下载,支持Linux、Windows 和 macOS平台…...
R包开发1:RStudio 与 GitHub建立连接
目录 1.安装Git 2-配置Git(只需配置一次) 3-用SSH连接GitHub(只需配置一次) 4-创建Github远程仓库 5-克隆仓库到本地 目标:创建的R包,包含Git版本控制,并且能在远程Github仓库同步,相当于发布在Github。…...
红蓝攻防:浅谈削弱WindowsDefender的各种方式
前言 随着数字技术的日益进步,我们的生活、工作和娱乐越来越依赖于计算机和网络系统。然而,与此同时,恶意软件也日趋猖獗,寻求窃取信息、破坏系统或仅仅为了展现其能力。微软Windows,作为世界上最流行的操作系统&…...
什么是响应式设计(Responsive Design)?如何实现一个响应式网页?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 响应式设计(Responsive Design)⭐ 如何实现一个响应式网页?1. 弹性网格布局2. 媒体查询3. 弹性图像和媒体4. 流式布局5. 优化导航6. 测试和调整7. 图片优化8. 字体优化9. 渐进增强10. 面向移动优先11. …...
QT之应用程序执行脚本
简介 ● Qt中的类QProcess支持在程序中另外开辟线程 ● 其中start方法支持以字符串为参数执行命令 以Linux平台为例: 方式一(后台执行) /// /// \brief MainWindow::cmdLine run a linux command with string format in the bash /// \pa…...
学习文档链接
SpringBoot Activiti 完美结合,快速实现工作流(最详细版) - 知乎 (zhihu.com) easypoi: POI 工具类,Excel的快速导入导出,Excel模板导出,Word模板导出,可以仅仅5行代码就可以完成Excel的导入导出,修改导出格式简单粗暴,快速有效,easypoi值得…...
【Java 高阶】一文精通 Spring MVC - 转换器(五)
👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区&#x…...
【HSPCIE仿真】输入网表文件(1)基本内容和基本规则
输入网表文件 1. 输入网表文件基本内容2. 输入网表文件示例3. 一些基本规则4. 数值表示5. 压缩文件格式的读取6. 参数和表达式 从HSPICE的仿真流程看,出去初始化配置过程,真正的仿真是从输入网表文件开始的。 HSPICE 根据输入网表文件( inpu…...
JPEXS Free Flash Decompiler社区大使选拔流程:申请与评审完全指南
JPEXS Free Flash Decompiler社区大使选拔流程:申请与评审完全指南 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler JPEXS Free Flash Decompiler是一款功能强大的Flash反编译…...
告别网络依赖:用这个开源工具+高德离线包,5步搞定前端地图离线展示
前端开发者的离线地图解决方案:5步实现高德地图本地化部署 在紧急演示、内网开发或网络不稳定的环境中,依赖在线地图服务往往成为前端开发的痛点。我曾参与过一个政府内网项目,现场演示时因网络权限问题导致地图无法加载,最后不得…...
英雄联盟智能工具League Akari:提升游戏体验的终极指南
英雄联盟智能工具League Akari:提升游戏体验的终极指南 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League Akari是…...
springboot框架-美妆化妆品商城进货系统
目录系统架构设计技术选型与依赖数据库设计核心功能实现库存预警机制前端交互建议测试与部署扩展性考虑项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作系统架构设计 采用SpringBoot MyBatis-Plus MySQL构建后端,…...
文档下载工具:突破平台限制的高效获取策略与零成本解决方案
文档下载工具:突破平台限制的高效获取策略与零成本解决方案 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本就是…...
LCDWIKI SPI图形库:嵌入式TFT-LCD驱动核心架构与实战
1. LCDWIKI SPI 图形库深度解析:面向嵌入式显示驱动的底层架构与工程实践LCDWIKI SPI Library 是一款专为基于 SPI 接口的 TFT-LCD 显示模块设计的轻量级、高兼容性图形驱动核心库。它并非孤立的显示驱动,而是整个 LCDWIKI 显示生态系统的“基石类”&…...
TVM终极模型剪枝指南:如何快速实现结构化与非结构化剪枝
TVM终极模型剪枝指南:如何快速实现结构化与非结构化剪枝 想要让深度学习模型跑得更快、占用更少内存?TVM的模型剪枝功能就是你的最佳选择!🚀 本文为你带来TVM剪枝的完整指南,从基础概念到实际应用,让你快速…...
高效实现Windows任务栏个性化的5个极简方案:轻量级透明化工具TranslucentTB全指南
高效实现Windows任务栏个性化的5个极简方案:轻量级透明化工具TranslucentTB全指南 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB …...
HunyuanVideo-Foley音效生成:支持SMPTE时间码对齐视频关键帧
HunyuanVideo-Foley音效生成:支持SMPTE时间码对齐视频关键帧 1. 产品概述 HunyuanVideo-Foley是一款专为影视后期制作设计的AI音效生成工具,其核心创新在于支持SMPTE时间码精确对齐视频关键帧。这意味着音效师可以基于视频时间轴上的特定帧,…...
原子操作的实现原理
在并发编程、操作系统与计算机体系结构中,原子操作是保证数据安全、避免竞态条件的基石。它的核心特性是不可中断、不可分割,操作要么完整执行,要么完全不执行,绝不会出现中间状态。本文将从定义出发,逐层拆解原子操作…...
