Skip to Content
面试题库Jvm[面试题] JVM 如何保证对象分配内存过程的线程安全?一个对象的结构是什么样的?

[面试题] JVM 如何保证对象分配内存过程的线程安全?一个对象的结构是什么样的?

📖 版块 A:知识讲解版 (温故知新)

  • 对象分配为什么会有线程安全问题

    1. 堆是线程共享区域。
    2. 多个线程同时分配对象时,如果没有控制,就可能发生地址重叠和数据覆盖。
  • JVM 常见保障手段

    1. CAS + 失败重试:在共享分配区中通过原子操作更新指针。
    2. TLAB(Thread Local Allocation Buffer):给每个线程在 Eden 中划一小块私有分配缓冲区,绝大多数对象先在这里快速分配。
  • 一个对象的典型结构

    1. 对象头

      • Mark Word:包含哈希码、GC 年龄、锁状态等。
      • 类型指针:指向类元数据。
      • 数组对象还会额外记录数组长度。
    2. 实例数据:对象真正的字段内容。

    3. 对齐填充:为了满足内存对齐要求,可能补齐若干字节。


🎤 版块 B:面试实战版 (高手逐字稿)

Q:JVM 如何保证对象分配内存过程的线程安全?一个对象的结构是什么样的?

💬 高手逐字稿

JVM 之所以需要考虑对象分配的线程安全,是因为堆本身是线程共享的。多个线程如果同时 new 对象,而内存指针又没有被正确同步,就可能出现两个线程分配到同一段地址的灾难性问题。

常见的解决方案主要有两个。

第一个是 CAS + 重试。也就是在共享分配区里,用原子操作去更新内存分配指针。如果竞争失败,就自旋重试。这种方式比较通用,但并发很高时会有冲突成本。

第二个是 TLAB,也就是线程本地分配缓冲区。JVM 会在 Eden 区里先给每个线程划一小块私有空间,大多数小对象优先在这块私有缓冲区里分配。这样绝大多数时候,线程分配对象根本不需要和别人竞争,大幅降低了同步开销。

再说对象结构。一个 Java 对象在内存里,通常可以拆成三部分:

第一部分是对象头。对象头里最重要的是 Mark Word,它会记录对象的哈希码、GC 年龄、锁状态等信息;另外还有一个类型指针,指向这个对象所属类的元数据。如果是数组对象,还会额外记录数组长度。

第二部分是实例数据,也就是我们真正定义的成员变量。

第三部分是对齐填充。因为 HotSpot 为了提升访问效率,通常要求对象大小满足特定对齐规则,所以必要时会补一些字节。

所以一句话总结:

  • 对象分配安全主要靠 TLAB 和 CAS
  • 对象内存布局主要分成 对象头、实例数据、对齐填充
最后更新于:
⏱️

登录后开始阅读

当前 MVP 版本只开放邮箱密码登录注册。完成登录后即可进入面试题内容。

还没有账号?先去注册