注:更多文章,可以进入我的博客:筱白博客
在介绍对象在内存中的组成结构前,我们先简要回顾一个对象的创建过程:
1、jvm通过类加载机制将class文件加载到方法区。
2、jvm把将要调用该类的方法入栈。
3、在堆(逃逸分析)中为对象分配内存空间,并将栈中的引用指向堆中的对象。
所以当对象在实例化完成之后,这里的对象由3部分组成,如下图所示:
各部分简要概括:
- 对象头:对象头存储的是对象在运行时状态的相关信息、指向该对象所属类的元数据的指针,如果对象是数组对象那么还会额外存储对象的数组长度
- 实例数据:实例数据存储的是对象的各个属性字段的值,如果在拥有父类的情况下,还会包含父类的属性字段。
- 对齐填充字节(非必要):因为64位的JVM要求对象的大小是8字节的倍数,因此当对象的大小不足8字节的整数倍时,需要在对象中进行填充操作。
对象分为普通对象和数组对象,两者的对象头内容不同,如是数组对象,其对象头里还包含数组长度。
① Mark Word(标记字)在Mark Word里,记录了对象的锁状态(锁标志位)、hashcode的值、线程指针ID、分代年龄、GC标记等信息。
hashcode的值只有在第一次调用hashcode()方法时才会写入
② Klass Pointer(类型指针)klass Pointer是一个指向方法区中Class信息的指针,虚拟机通过这个指针确定该对象属于哪个类的实例。
在64位的JVM中,支持指针压缩功能,根据是否开启指针压缩,Klass Pointer占用的大小将会不同:
- 未开启指针压缩时,类型指针占用8Byte (64bit)
- 开启指针压缩情况下,类型指针占用4Byte (32bit)
如果当对象是一个数组对象时,那么在对象头中有一个保存数组长度的空间。
User[] user=new User[2];2、实例数据
实例数据存储的是对象的各个属性字段的值,如果在拥有父类的情况下,还会包含父类的属性字段。
对象属性字段不包括类属性(被static修饰的)
3、对齐填充(非必要)因为64位的JVM要求对象的大小是8字节的倍数,因此当对象的大小不足8字节的整数倍时,需要在对象中进行填充操作。



