对象内存模型

创建对象的步骤

创建一个对象Object object = new Object();

从字节码角度


在这里插入图片描述

  • new:如果找不到Class实例对象,就会对该类进行加载。加载成功后,在堆中分配内存。内存分配完毕后,将指向这个实例对象的引入放入栈顶
  • dup:将栈顶的实例变量的引用复制一份,这时两个实例变量的引用指向了同一个对象实例。如构造方法()有参数,会将参数放入操作数栈中。
  • INVOKESPECIAL:用栈顶的引用,调用init<>的构造方法。



从执行步骤的角度

  1. 判断类是否被加载
  2. 在堆中分配内存地址
  3. 除了并发安全问题(TLAB、CAS)
  4. 对对象中的实例变量进行初始化。即设置默认值
  5. 设置对象的对象头
  6. 指向init<>方法进行初始化



从内存的角度

见jvm堆中对象的创建


对象的内存布局

对象的内存布局中,数组对象和一般对象的内存布局有点不一样,数组的内存布局多一个长度字段,其余的都是一样的。
图示:该图来源于网络
在这里插入图片描述

其中

  • MarkWord是对象中的一些信息,如hashCode、锁的类型、GC分代年龄
  • Klass Pointer的这个对象指向的类信息的指针
  • Instance Data:是这个对象中的实例变量数据
  • 对其填充的保证对象占用的是8的倍数的字节

对象头的说明:

在这里插入图片描述

因为对象头中包含锁的信息,而锁的信息的知识是JUC中的synchronized的知识,所以这里就关注第一个无锁的状态。
可以看到,对象头占用了68位bit,即8字节。在无锁情况下,有26位都是没有被使用的。

代码测试:
测试类:

public class User {

    int age = 10;
    boolean a = false;
    char c = 'a';
}

需要引入maven依赖:

        <!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
        <dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.16</version>
        </dependency>

测试代码1:

    public static void main(String[] args) {
        User user = new User();
        System.out.println(ClassLayout.parseInstance(user).toPrintable());
    }

输出:
在这里插入图片描述

可以看到,输出的结果以次是:对象头信息、类信息的指针、实例数据、字段补充
其中有一些不一样的信息:

  • 对象头信息的hashCode是为0,这是因为hashCode要在调用hashCode的时候才会被赋值
  • 类指针是占用的4字节,而不是8字节。主要是使用了指针压缩,可以使用-XX:-UseCompressedClassPointers来关闭指针压缩
  • 实例变量占用的字节和Java基础中描述的是一样的。但是其在内存被根据类型的大小对数据进行重排,这就可以提高内存的利用率,如图:

在这里插入图片描述

  • 补充位是将内存补充为8的整数被字节。这里补充到了24为。

测试代表2:调用了hashCode,并且关闭指针压缩-XX:-UseCompressedClassPointers

    public static void main(String[] args) {
        User user = new User();
        user.hashCode();
        System.out.println(ClassLayout.parseInstance(user).toPrintable());
    }

在这里插入图片描述

对象头的16进制为为:

0x0000006e0be85801 对应的二进制如下:
00000000 00000000 00000000 01101110 00001011 11101000 01011000 00000001
0x6e0be858 对应的二进制如下:
01101110 00001011 11101000 01011000

完成符合前面的概念,对象头也是一样的

宋红康老师的对象布局图

宋红康老师的对象布局图可以说是最详细的布局图,图如下:
在这里插入图片描述

对象的访问定位

即用哪种方式访问到对象的位置,有句柄访问直接使用指针访问

句柄访问

即通过一个中间状态来关联对象实例和对象的类
在这里插入图片描述

好处:在进行垃圾回收后,对象的移动只需要改变中间状态的指针即可,不用修改栈中的指针


直接使用指针访问

这是hosport虚拟机的访问方式,也是前面对象布局中的结果,直接将类型指针放在对象实例数据中
在这里插入图片描述

好处:好处:速度更快,java中对象访问频繁,每次访问都节省了一次指针定位的时间开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值