JUC: Java对象内存布局和对象头

4.9.1 面试题

12、你觉得目前面试,你还有那些方面理解的比较好,我没问到的,我说了juc和 jvm以及 同步锁机制

那先说juc吧,说下aqs的大致流程3、

14、cas自旋锁,是获取不到锁就一直自旋吗? cas和synchronized区别在哪里,为什么cas好,具体优势在哪里,我说cas避免cpu切换线程的开销,又问我在自旋的这个线程能保证一直占用cpu吗?假如cpu放弃了这个线程,不是还要带来线程再次抢占cpu的开销?

15、synchronized底层如何实现的,实现同步的时候用到cas了吗?具体哪里用到了

16、我说上个问题的时候说到了对象头,问我对象头存储哪些信息,长度是多少位存储

4.9.2 对象在堆内存中布局

在HotSpot虚拟机中,对象在堆内存中的存储布局可以划分为三个部分:对象头(Header),实例数据(Instance Data),和对齐填充(Padding)

  • 对象实例
    • 对象头
      • 对象标记(Mark Word):HashCode,GC标记,GC存活次数,同步锁标记,偏向锁持有者
      • 类元信息(又叫类型指针):指向该对象类元数据(klass)的首地址
      • 长度(数组对象特有)
    • 实例数据(属性数据)
    • 对齐填充(保证8字节的倍数)

在64位系统中,Mark Word占用8字节,类元信息占用8字节,一共是16字节。

Object obj = new Object(); // obj占用16字节的数据

// 类元信息(类型指针)
Customer c1 = new Customer(); // c1中的类型指针指向了Customer类

class Customer{ 
	int id;  // 实例数据
}

JOL查看Java对象内存布局

<!-- JOL依赖 JOL查看Java对象内存布局-->
<dependency>
   <groupId>org.openjdk.jol</groupId>
   <artifactId>jol-core</artifactId>
   <version>0.9</version>
</dependency>
  • 两种方式
    • 开启偏向锁无等待 -XX:BiasedLockingStartupDelay=0
    • 使用Sleep
public class JOLTest {
    public static void main(String[] args) throws InterruptedException {
        Object o = new Object();
        TimeUnit.SECONDS.sleep(5);
        synchronized (o) {
            System.out.println(ClassLayout.parseInstance(o).toPrintable());
        }
    }
}

(1) 对象标记MarkWord

image

分代年龄最大为15,因为对象标记(MarkWord)中GC存活次数只占4个bit位,只能表示 0 ~ 15

posted @ 2025-09-30 12:28  飞↑  阅读(9)  评论(0)    收藏  举报