大厂面试(二)请描述new Object()的内存布局—美团

JOL:( Java Object Layout),new 一个 Object 对象,看这个对象的内存布局?平时我们new一个对象出来,在堆里申请一块内存,那么这块内存的布局到底是什么样的呢?

这块内存的布局分为4个部分:

第一部分:markwork

第二部分:classpointer

第三部分:instanceData

第四部分:padding

前两部分称为Object header 对象头,其中第二部分classpointer为类指针,表明这个对象所属哪个类,比如对象Object,那么它的所属类就是Object.class,第三部分instanceData为实例数据,用来装成员变量,第四部分padding为补齐,一个对象的字节数必须能被8整除,不能整除的加padding对齐。

我们引入org.openjdk.jol包,用Java程序打印下它的内存结构

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.9</version>
</dependency>
public static void main(String[] args) {
    Object o = new Object();
    System.out.println(ClassLayout.parseInstance(o).toPrintable());
}
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION             VALUE
      0     4        (object header)         01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)         00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)         e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


Process finished with exit code 0

OFFSET表示从多少个字节开始,SIZE表示到OFFSET后的第几位,那么来看数据中的第一行:

从第0个字节开始,往后数4个字节,再看第二行:

从第4个字节开始,往后数4个字节,这两部分构成我们图中的markword,一共8个字节。再看第三行:

从第8个字节开始,往后数4个字节,这部分是我们图中的classpointer,指向Object.class这个类。再看第四行:

从第12个字节开始,往后数4个字节,loss due to the next object alignment对象的对齐被丢掉了,什么意思?我们前面一共是3x4=12个字节,12不能被8整除,所以加了4个字节能够被8整除,所以最后的这4个字节是用来对齐用的。

MarkWord是干嘛用的?

有三个作用:

  1. 记录锁信息
  2. 记录GC
  3. 记录HashCode (identity HashCode)

后两个不是我们讨论的内容,主要说第一个,记录锁信息,那这个markword到底怎么记录的呢?

我们在这个对象加把锁,再看下它的内存布局,和之前的对比下

public static void main(String[] args) {
    Object o = new Object();
    System.out.println(ClassLayout.parseInstance(o).toPrintable());

    synchronized (Jol.class) {

      	System.out.println(ClassLayout.parseInstance(o).toPrintable());
    }
}
java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION              VALUE
      0     4        (object header)          01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4        (object header)          00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4        (object header)          e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

  
  
java.lang.Object object internals:
 OFFSET  SIZE   TYPE DESCRIPTION              VALUE
   0     4        (object header)             90 c9 37 0e (10010000 11001001 00110111 00001110) (238537104)
   4     4        (object header)             00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
   8     4        (object header)             e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243)
     12     4        (loss due to the next object alignment)
Instance size: 16 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

看到了吗,加了锁的对象和不加锁的对象前两行VALUE值是不一样的,也就是markword是不一样的,所以说,给对象加锁就是修改了markword的值。

markword里面的内容都代表什么意思?来参考一张图

这是new Object() markword里面最低位值的参考

你可能有疑问,不是看最低位字节吗,不应该是最后面吗,怎么看最前面的?Little-Endian字节序,低位字节排在最前,只有网络传输的时候才是Big-Endian高位字节在前。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YoungJ5788

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值