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

【深入理解jvm读书笔记】jvm如何进行内存分配

jvm如何进行内存分配

        • 内存分配方式
        • 内存分配方式的选择
        • 并发场景下的内存分配
        • 内存空间的初始化
        • 构造函数

内存分配方式

  • 指针碰撞
  • 空闲列表

指针碰撞法:

假设Java堆中内存是绝对规整的,所有被使用过的内存都被放在一边,空闲的内存被放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间方向挪动一段与对象大小相等的距离,这种分配方式称为“指针碰撞”

空闲列表法:

但如果Java堆中的内存并不是规整的,已被使用的内存和空闲的内存相互交错在一起,那就没有办法简单地进行指针碰撞了,虚拟机就必须维护一个列表记录上哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录,这种分配方式称为“空闲列表”

内存分配方式的选择

Java堆是否规整又由所采用的垃圾收集器是否带有空间压缩整理(Compact)的能力决定。因此,当使用Serial、ParNew等带压缩整理过程的收集器时,系统采用的分配算法是指针碰撞,既简单又高效;而当使用CMS这种基于清除(Sweep)算法的收集器时,理论上就只能采用较为复杂的空闲列表来分配内存。

并发场景下的内存分配

并发场景下可能出现多个线程同时创建对象的情况,这种时刻的内存分配是明显存在问题的,如果在给A对象分配好内存了,但是指针还没来得及修改,此时B对象刚获取指针的位置并且分配内存那么就会造成内存区域重叠,这种情况的处理方案有两种。

  1. 一种是对分配内存空间的动作进行同步处理——实际上虚拟机是采用CAS配上失败重试的方式保证更新操作的原子性

  2. 另外一种是把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local AllocationBuffer,TLAB,哪个线程要分配内存,就在哪个线程的本地缓冲区中分配,只有本地缓冲区用完了,分配新的缓存区时才需要同步锁定

其实第一种方案就是给分配内存的操作加锁,指针碰撞的时候每个线程都不断尝试获取锁,而拿到锁的线程只有分配完对象内存空间并且修改指针后,才释放锁并通知其他线程,保证原子性。而加锁必然会造成性能上的开销,但是如果使用第二种方式,即使用缓冲区也就是经典的以空间换时间思想来减少加锁操作保证运行的效率。

内存空间的初始化

内存分配完成之后,虚拟机必须将分配到的内存空间(但不包括对象头)都初始化为零值,如果使用了TLAB的话,这一项工作也可以提前至TLAB分配时顺便进行。这步操作保证了对象的实例字段在Java代码中可以不赋初始值就直接使用,使程序能访问到这些字段的数据类型所对应的零值。

构造函数

在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了。但是从Java程序的视角看来,对象创建才刚刚开始——构造函数即Class文件中的()方法还没有执行,所有的字段都为默认的零值,对象需要的其他资源和状态信息也还没有按照预定的意图构造好。

一般来说(由字节码流中new指令后面是否跟随invokespecial指令所决定,Java编译器会在遇到new关键字的地方同时生成这两条字节码指令,但如果直接通过其他方式产生的则不一定如此),new指令之后会接着执行init()方法,按照程序员的意愿对对象进行初始化,这样一个真正可用的对象才算完全被构造出来。

http://www.lryc.cn/news/134451.html

相关文章:

  • OpenCV使用CMake和MinGW-w64的编译安装
  • 亚马逊买家怎么留评
  • 并查集 size 的优化(并查集 size 的优化)
  • Qt关于hex转double,或者QByteArray转double
  • Java“牵手”根据关键词搜索(分类搜索)拼多多商品列表页面数据获取方法,拼多多API实现批量商品数据抓取示例
  • Linux相关知识点
  • 常见的的数据结构
  • 专业心理咨询师助你轻装上阵,向内耗说不!
  • Ubuntu安装mysql5.7
  • vue2,使用element中的Upload 上传文件,自定义上传http-request上传,上传附件支持多选,多个文件只发送一次请求,代码里有注释
  • flutter定位简单工具类
  • java请求SAP系统,发起soap的xml报文,实体类转换,idea自动生成教程
  • 不同屏幕的触控技术
  • 深度解读thenable
  • 原生无限极目录树详细讲解
  • 剑指offer(C++)-JZ64:求1+2+3+...+n(算法-位运算)
  • “深入探究JVM内部机制:如何实现Java程序的运行环境?“
  • Mac更新homebrew时卡住的解决办法
  • 带你了解—在外远程群晖NAS-群晖Drive挂载电脑磁盘同步备份【无需公网IP】
  • 计算机网络第2章(物理层)
  • windows钩子保护自身进程不被破坏
  • Linux系统查看文件系统类型C代码
  • Python中的正则表达式
  • 第六章,创作文章
  • Win10c盘满了怎么清理?快速清理,5个方法!
  • 回归预测 | MATLAB实现GWO-BP灰狼算法优化BP神经网络多输入单输出回归预测(多指标,多图)
  • docker 06(docker compose)
  • 非阻塞重试与 Spring Kafka 的集成测试
  • 基于 Debian 12 的MX Linux 23 正式发布!
  • Nginx代理功能与负载均衡详解