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

Java的内存模型

它定义了 Java 程序中变量的内存可见性、原子性和有序性,确保了多线程环境下的正确性.

核心问题:

  • 内存可见性:线程之间无法及时看到其他线程对共享变量的修改
  • 指令重排序:为了提高执行速度,编译器和处理器可能会对指令进行重排序优化
  • 线程的安全: 线程的原子性

new 出一个东西的过程是什么?

  • 类的加载检查。
  • 分配内存,分配内存的方式有 “指针碰撞” 和 “空闲列表” 两种
  • 初始化零值,JVM 会将分配到的内存空间都初始化为零值
  • 设置对象头
  • 执行初始的方法

从JMM来解释:
可见性:

JVM 会通过内存屏障等机制来保证对象的初始化操作在主内存中完成,从而让其他线程能够看到对象的最新状态。

初始化:

MM 规定了一些规则来禁止特定类型的指令重排序,以保证对象的初始化顺序符合程序员的预期。

new出来一个对象,会有什么分配内存的方式:
  • 指针碰撞:
    • 假设 Java 堆中的内存是绝对规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离。
    • 使用场景:空间压缩整理功能的垃圾收集器,如 Serial、ParNew 等
  • 空闲列表:
    • 如果 Java 堆中的内存并不是规整的,已使用的内存和空闲的内存相互交错,那就没有办法简单地进行指针碰撞了,虚拟机就必须维护一个列表,记录上哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录。
    • 适用于使用不具备空间压缩整理功能的垃圾收集器,如 CMS 这种基于标记 - 清除算法的垃圾收集器

并发环境下分配内存的问题及解决办法:

  • 1.使用了cas的机制,不断地进行重试。在内存分配时,使用 CAS 操作来保证对内存分配指针的原子性更新,如果操作失败则重试,直到成功为止。
  • 2.本地线程分配缓存(TLAB):
    • 每个线程在 Java 堆中预先分配一小块私有内存,称为 TLAB。线程在分配对象时,首先在自己的 TLAB 上进行分配,如果 TLAB 空间足够,就直接在 TLAB 上分配内存,这样就避免了多线程之间的竞争。只有当 TLAB 空间不足时,才会采用 CAS 等方式在公共的堆空间上分配内存。

TLAB会给每个线程划分一块小小的区域,比如100KB,但是随着线程的运行比如调用栈特别深,new了很多对象,TLAB内存不够了,这时候需要怎么办?

  • 尝试重新分配TLAB
  • 大对象直接在Eden分配
  • 如果Eden也满了,那么触发Minor GC

相关文章:

  • 高等数学同步测试卷 同济7版 试卷部分 上 做题记录 第二章导数与微分同步测试卷A卷
  • Java Lambda与方法引用:函数式编程的颠覆性实践
  • Soybean Admin 配置vite兼容低版本浏览器、安卓电视浏览器(飞视浏览器)
  • “pip“ is not recognized(pip无法被识别)
  • VBA即用型代码手册:书签Bookmarks
  • ARCGIS PRO 在已建工程地图中添加在线地图
  • Soybean Admin移除git-hooks永久关闭git校验
  • 【算法】——一键解决动态规划
  • spdlog高速日志系统
  • recyclerview嵌套,实现水平方向联合滑动
  • 音频转文本:如何识别音频成文字
  • Maven超级详细安装部署
  • 第十四届蓝桥杯大赛软件赛国赛Python大学B组题解
  • 在 Q3D 中提取汇流条电感
  • Google Chrome下载受限制的解决方案【方法指南】
  • 【原创】vue-element-admin-plus完成确认密码功能,并实时获取Form中表单字段中的值
  • openlayers入门01 -- 环境配置和初始化地图
  • 今日行情明日机会——20250410
  • OceanBase单机版保姆级安装
  • MPP 架构解析:原理、核心优势与对比指南