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

面试tips--JVM(1)--对象分配内存的方式TLAB

1. 对象分配的基本方式

当 Java 程序创建对象时(new Object()),JVM 需要在 堆内存 中为对象分配空间。分配方式主要有两种:

(1)指针碰撞(Bump-the-Pointer)

  • 场景:堆内存是 规整的(即所有空闲空间都集中在一侧,已使用空间在另一侧,中间用指针隔开)。

  • 机制:维护一个指针(如 top),对象分配时只需把指针向前移动一段等于对象大小的距离即可。

  • 优点:非常高效,O(1) 操作。

  • 前提:堆必须是连续且规整的,通常依赖 垃圾收集器(如复制算法、G1的Region内存整理) 来保持堆的规整性。

(2)空闲列表(Free List)

  • 场景:堆内存 不规整(存在很多分散的小空闲块)。

  • 机制:JVM 维护一个 空闲内存块列表,对象分配时从列表中找到一块足够大的空间(可能涉及首次适配、最佳适配等策略)。

  • 优点:适用于碎片化的内存。

  • 缺点:需要遍历或管理链表,性能比指针碰撞低。


2. TLAB(Thread Local Allocation Buffer,线程本地分配缓冲区)【相当于指针碰撞的优化策略】

  • 背景:在多线程环境下,如果所有线程都直接在堆上分配对象,会涉及全局指针的竞争,导致加锁开销。

  • 机制:JVM 为每个线程分配一个 小块堆内存私有区域(TLAB)

    • 每个线程优先在自己的 TLAB 中分配对象,不需要加锁,效率接近 指针碰撞

    • TLAB 内存用完时,线程再向堆申请新的 TLAB(这个申请动作可能涉及锁)。

  • 关系

    • TLAB 内部使用指针碰撞:因为 TLAB 本身是一个连续的内存块,线程在其中分配对象时,只需移动指针即可。

    • 如果 TLAB 无法满足对象大小TLAB 已满,线程才会退回到全局堆分配,此时可能使用 指针碰撞(若堆规整)或 空闲列表(若堆不规整)。

为啥要优化?

①.指针碰撞(Bump-the-Pointer)的问题
  • 原理:堆是规整的,空闲的内存空间连续排列。分配对象时,只需要把一个“分配指针”往前挪动一段距离(对象大小),就能得到新对象的内存区域,非常快。

  • 并发问题
    在多线程环境下,多个线程可能同时尝试修改这个“分配指针”。

    • 线程 A 还没来得及更新指针

    • 线程 B 也在修改指针
      → 可能导致两个对象分配到同一片内存,产生覆盖或数据错乱。


②解决方法

JVM 提供了两种方案:

(1) 加锁(CAS 或同步)
  • 对全局的分配指针操作加锁或使用 CAS,保证同一时间只有一个线程可以移动指针。也就是说是对分配内存空间的动作进行同步处理—— 实际上虚拟机是采用 CAS 配上失败 重试的方式保证更新操作的原子性;

  • 缺点:多线程竞争时会有锁开销,影响性能。

(2) 使用 TLAB(Thread Local Allocation Buffer)
  • 原理:给每个线程在 Eden 区预分配一小块私有的内存区域(TLAB)。

  • 线程在自己的 TLAB 内部分配对象时,不需要加锁,可以直接用指针碰撞的方式分配,非常快。

  • 当 TLAB 用完时,再申请新的 TLAB,才会涉及全局堆的同步操作。


3. 三者关系总结

  • 指针碰撞:最高效的分配方式,适用于规整的堆。

  • 空闲列表:适用于堆不规整,有内存碎片时使用。

  • TLAB:线程私有的分配缓冲区,本质上仍依赖 指针碰撞,是为了解决多线程竞争堆分配的问题。【相当于指针碰撞的优化策略

一句话总结
对象分配时,线程会先在自己的 TLAB(基于指针碰撞) 中分配;如果失败,则退回全局堆,全局堆会根据是否规整选择 指针碰撞空闲列表

4. 小贴士

  • 分配方式选择规则

    • 堆规整(比如新生代 Eden 区):👉 指针碰撞

    • 堆不规整(比如老年代 CMS):👉 空闲列表

  • TLAB:是 指针碰撞 的线程私有优化,优先分配;分配失败才退化到全局分配。

http://www.dtcms.com/a/356057.html

相关文章:

  • CTFshow系列——命令执行web61-68
  • C++之多态篇
  • 君正T31学习(四)- MT7682+VLC出图
  • 【python】python进阶——as关键字
  • 程序代码篇---类
  • SpringCloud Alibaba Nacos 注册中心/配置中心
  • SpringBoot 配置文件在运维开发中的应用
  • 基于springboot的商业店铺租赁系统
  • 在 Vue 前端(Vue2/Vue3 通用)载入 JSON 格式的动图
  • 校园文化活动管理系统设计与实现(代码+数据库+LW)
  • web前端知识——第一阶段
  • 【buildroot】【1. Buildroot版本与Linux内核调试对应关系】
  • 基于SpringBoot的旅游景点推荐系统【2026最新】
  • 域名所有权变更,需要重新备案吗
  • Day16_【机器学习分类】
  • 软磁材料与硬磁材料
  • MTK Linux DRM分析(十九)- KMS drm_framebuffer.c
  • LeetCode 141.环形链表
  • 软考中级【网络工程师】第6版教材 第4章 无线通信网 (上)
  • 8.28 JS移动端事件
  • HTTP 范围请求:为什么你的下载可以“断点续传”?
  • 现在购买PCIe 5.0 SSD是否是最好的时机?
  • 嵌入式学习笔记--LINUX系统编程阶段--DAY02系统编程
  • 嵌入式学习日志————实验:串口发送串口发送+接收
  • 亚远景-ISO/PAS 8800:如何通过认证提升企业技术管理能力?
  • 入职体检空腹血糖 6.15mmol/L合格吗?
  • amis上传组件导入文件接口参数为base64格式的使用示例
  • NumPy 2.x 完全指南【三十一】布尔数组索引
  • ConcurrentHashMap的原理
  • 实战笔记——构建智能Agent:SpreadJS代码助手