当前位置: 首页 > 后端技术 > Java

JAVA并发编程——Java对象内存布局和对象头

时间:2023-04-01 14:24:59 Java

1。对象在堆内存中的布局2.对象对象头3.对象实例数据4.对象对齐填充5.查看对象对象头6.查看自定义对象的对象头7.总结1.对象在堆内存中的布局当我们写这么一行代码Objectobject=newObject();,我们都知道会在我们的JVM堆->新区->EdenPark创建一个新的对象,但是我们可能只知道这个对象在哪里,但是我们对对象的内存结构知之甚少。今天我们就来详细说说JAVA对象的内存布局。我们先来看这样一张图:java对象在内存中的布局分为以下三部分:1)对象头2)实例数据3)对齐填充接下来我们详细介绍以下三个部分。2.对象的对象头首先是对象头,它是java对象内存布局中最重要的部分。分为两部分:1)对象标记MarkWord2)类型指针(类元信息)首先是对象标记:默认存储HashCode、分代年龄、锁标志、GC标志等信息。这些信息是与对象本身的定义无关的数据,所以MarkWork被设计成一个非固定的数据结构,以便在小的空间内存储尽可能多的数据。它会根据对象的状态重用自己的存储空间,也就是说在运行过程中,MarkWork中的存储对象会随着锁标志的变化而变化。类型指针(类元信息):对象指向其类元数据的指针,虚拟机通过这个指针来判断该对象是哪个类实例。对象头的大小:在64位系统中,MarkWord占8个字节,类型指针占8个字节,共16个字节。3、对象的实例数据应该是我们每天接触的部分。我们平时写的字段都在这里,包括父类的属性信息(如果是数组的实例部分,还包括数组的长度)。这部分内存是按照4字节对齐的。4.对象对齐填充虚拟机要求对象的起始地址必须是8字节的整数倍,填充数据不一定要存在。如果对象头+对象实例数据不是8的整数倍,那么对象对齐填充将按照8字节补充对齐。5、查看Object的对象头在使用java查看Object的对象头之前,我们需要先引入一个工具类,这样我们可以更方便的查看对象头。org.openjdk.joljol-core0.9那我们试试看,看看我们平时用到的Object类的对象头有几个字节:publicstaticvoidmain(String[]args){Objecto=newObject();System.out.println(ClassLayout.parseInstance(o).toPrintable());}发现这里没有问题。前面我们说对象头占16个字节,这里只占12个字节?最后一行显示Missing?那么对象头是占16字节还是12字节呢?答案是——两者都是对的。因为JVM默认已经为我们开启了对象头的压缩。开启此压缩后,对象头占用12位。如果关闭此压缩,则对象头占用16位。再试一次:我们先在JVM运行时使用这个参数:-XX:-UseCompressedClassPointers这个参数是关闭压缩参数。然后再次运行,得到的结果是:6.看自定义对象的对象头看完了Object的对象头,我们来看看自定义的对象头有什么区别。我们先自定义一个对象类MyObj{privateIntegerid;私有字符串名称;私人整数年龄;私有字符串地址;私有整数状态;私人日期创建时间;定义的字段填充对齐。7.小结今天我们学习了JAVA对象在内存中的布局。这部分是为解锁和升级做铺垫。

猜你喜欢