侧边栏壁纸
  • 累计撰写 15 篇文章
  • 累计创建 10 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

[转载]Java对象在内存中的内存布局

骑摩托的程序员
2021-06-02 / 0 评论 / 0 点赞 / 741 阅读 / 0 字

一.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字节是用来对齐。具体结合下面这张图我们可以更容易剖析 20200702181225493.png

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

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

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

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

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

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

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

20200702183328917.png 对象头占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());

20200702184024402.png 我们自定义的对象中包含有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对象里。

20200702190017866.png

加锁执行后,我们发现原来对应的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

0

评论区