Java对象在内存中的内存布局

一.Java对象的内存占用大小

为了方便在程序中看到java对象内存布局,我们可以在maven中添加jol-core依赖

<dependency>
	<groupId>org.openjdk.jol</groupId>
	<artifactId>jol-core</artifactId>
	<version>0.9</version>
</dependency>

首先我们看下最简单的Object对象是怎么样的

Object o = new Object();
System.out.println(ClassLayout.parseInstance(o).toPrintable());

对象头总共占了12字节,剩下4字节是用来对齐。具体结合下面这张图我们可以更容易剖析

整个对象头(object header)占12个字节,分为markword和Class pointer。

markword占8个字节,关于锁的信息都记录在这里。类型指针表明这个对象到底属于哪个Class,占4个字节。实例数据指对象中的成员变量。对齐则是指当我们整体的字节数不能被8整除的时候,则会补到能被8整除的字节数。内存单元读取方式在计算机组成原理中有说明,可进一步了解。

关于类型指针,深入说明一下,

一般来说,JVM是64位系统,它的指针就应该是8个字节大小,但是由于它默认开启了UseCompressedClassPointers,也就是指针压缩,就会把这8个字节压缩成4个字节。所以我们上图那个类型指针在默认情况下就占4个字节。

所以回到我们的Object对象,实例数据为0字节,再加上对齐的4字节,总共便有16字节。

接着我们初始化一个int对象,看下其内存分布。

int i = 0;
System.out.println(ClassLayout.parseInstance(i).toPrintable());

对象头占12个字节,实例数据大小占4个字节,也就是我们说的int类型为4个字节。此时已达16字节,不需要再对齐了。

自定义对象内存大小:

@Data
public class User {
    int age;
    String name;
    Object o;
}
Object o = new Object();
User user = new User();
user.setO(o);
System.out.println(ClassLayout.parseInstance(user).toPrintable());

我们自定义的对象中包含有int 、String、Object,String在默认开启了普通对象指针压缩的情况下,即UseCompressedOops,占4个字节。

实例数据所占大小为4+4+4=12字节,总和为24字节,不需要对齐。

二.结合锁谈谈markword

Object o = new Object();
synchronized (o) {
    System.out.println(ClassLayout.parseInstance(o).toPrintable());
}

执行这块代码的时候,锁住object这个对象,锁的信息是记录在object对象里。

加锁执行后,我们发现原来对应的05 00 00 00变成了 05 70 0d 03,说明保存了锁的信息。

要具体了解锁升级过程中markword的变化,可查看synchronized锁升级过程

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值