对象内存布局详解

声明

64bit虚拟机和32bit虚拟机,对象所占内存是不一样的:

64位jvm中Mark Word占64bit;
32位jvm中Mark Word占32bit。

根据是否开启元数据类型指针:
如果开启- klass占8字节;
如果不开启(默认不开启)- klass占4个字节.
手动设置开启指针压缩:-XX:+UseCompressedOops

一、对象内存布局

1. 对象布局介绍

HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
在这里插入图片描述

1.1 对象头

• 对象头:比如 hash码,对象所属的年代,对象锁,锁状态标志,偏向锁(线程)ID,偏向时间, **数组长度(数组对象)**等。

1.1.1 对象头由两或三部分组成:

1.Mark Word
2.Klass pointer
3.数组长度(只有数组对象才有)

1.1.2 32bit的JVM对象头中的MarkWord存储

在这里插入图片描述

无锁状态的时候:只有调用了hashcode()才会生成hash码值。
对象头 - hashcode场景分析

偏向锁的hashcode存在哪呢?
– 推测可能在monitor中。

1.1.2 64bit的JVM对象头中的MarkWord存储

在这里插入图片描述

在这里插入图片描述

1.1.3 klass释义

对象通过klass这个地址值,到方法区找到元数据信息。

元数据指针:堆中的对象通过元数据指针(地址)找到方法区中的元数据信息。(Java对象在加载阶段,会创建一个java.lang.class类,可以通过反射的方式获取类的信息,类的信息存储在方法区,反射是通过元数据指针拿到信息的。)

1.1.4 为什么数组对象的对象头会多个数组长度

如果对象是数组类型,因为JVM虚拟机可以通过Java对象的元数据信息确定Java对象的大小,但是无法从数组的元数据来确认数组的大小,所以用一块来记录数组长度。

1.2 实例数据

• 实例数据:存放类的属性数据信息,包括父类的属性信息

注意:包括父类的属性信息。

1.3 对齐填充

• 对齐填充:由于虚拟机要求 对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐;

1.3.1为什么必须是8个字节?

根据“计算机组成原理”,8个字节是计算机读取和存储的最佳实践。

2.对象的创建与OOP-Klass模型的关系

对象的创建与OOP-Klass模型:

class Model
{
    public static int a = 1;
    public int b;
    public Model(int b) {
        this.b = b;
    }
}
public static void main(String[] args) {
    int c = 10;
    Model modelA = new Model(2);
    Model modelB = new Model(3);
}

在这里插入图片描述

方法区:类(元数据)信息、类变量(静态变量和常量)、方法信息
类的信息如:类名,类路径,类中方法,类中的属性等等;
方法信息:方法的名字,方法有多少个等等;
切记:方法信息只存有关方法的信息,不存方法里面具体内容。具体的内容是字节码执行引擎在执行每个方法的时候在Java虚拟机栈生成栈帧进行存储的。
堆:对象、成员变量
栈:局部变量

3.Oop-Klass模型于反射的关系

Java对象在加载阶段,会创建一个java.lang.class类,可以通过反射的方式获取类的信息,类的信息存储在方法区,反射是通过元数据指针拿到信息的。

从Oop-Klass模型看透反射

结语

在了解对象头中的具体内容后,我们开始研究在并发场景下,对象头中的状态是如何变化的?

二、锁膨胀过程详解讲解

下一篇:synchronized锁升级详细讲解案例:代码+流程图

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐