一.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锁升级过程 ———————————————— 版权声明:本文为CSDN博主「剑拔弩张的Logan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_38824137/article/details/107089862
评论区