Java虚拟机对象创建过程

本文详细探讨了Java虚拟机(JVM)中对象的创建过程,包括类加载检查、内存分配(指针碰撞与空闲列表、线程安全的分配策略)、对象头的设置、实例数据初始化以及对象的定位访问。对象内存布局分为对象头、实例数据和对齐填充三部分,其中对象头包含了对象类型指针和运行时数据。对象的访问方式有句柄访问和直接访问两种。了解这些机制有助于深入理解Java内存管理和性能优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java虚拟机对象创建过程

1、对象的内存分配方法

  1. 类加载检查,首先检查类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。

  2. 类加载检查通过之后,需要为新生对象分配内存,分配内存有两种方法:

    • **指针碰撞**

    • **空闲列表**

  3. 对象创建应该是线程安全的,例如给对象分配完内存之后,需要修改栈区中指向堆内存堆的指针,这个过程未必是线程安全的。实现内存分配指针修改的线程安全,有两种方法:

    • **CAS配上失败重试**保证更新操作的原子性

    • **本地线程分配缓冲**(Thread Local Allocation Buffer,TLAB),为每一个线程在Java堆中预先分配一小块内存,只有本地缓冲区用完之后,分配新缓存区才需要同步锁定

  4. 内存分配完成之后,虚拟机必须将分配到的内存空间(但不包括对象头)都初始化为零值,保证了在Java代码中可以不赋初始值就直接使用

  5. **对象头**进行设置,对象头包括:

    • 类的元数据信息

    • 对象的哈希码

    • 对象GC分代年龄

  6. 对对象进行初始化,包括执行构造函数、静态代码段执行
    在这里插入图片描述


2、对象的内存把布局

  1. 对象在内存中的存储布局可以分为三个部分:

    • 对象头

    • 实例数据

    • 对齐填充

  2. 对象头包括两部分信息

    • 对象运行时数据,包括哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,这部分数据的长度在32位和64位的虚拟机(未开启压缩指针)中分别为32个比特和64个比特,官方称它 为“Mark Word”

    • 对象类型指针,即对象指向它的类型元数据的指针,Java虚拟机通过这个指针 来确定该对象是哪个类的实例

  3. 实例数据,对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字段内容

  4. 对齐填充

    • HotSpot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是 任何对象的大小都必须是8字节的整数倍,对不满足要求的部分进行填充。

在这里插入图片描述


3、对象的定位访问

  1. 对象的访问方式主要有两种:

    • 句柄访问

    • 直接访问

  2. 句柄访问

    • reference存放的是对象句柄地址,包括**对象实例数据****类型数据**,实例数据位于堆内存中,指的是类中的各个字段。类型数据即对象的方法,位于方法区,由对象头中的对象类型指针指向

    • 句柄访问的好处在于reference中存储的是稳定句柄地址,在对象被移动(垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针,而 reference本身不需要被修改。
      在这里插入图片描述

  3. 直接访问

    • reference存储的是对象地址,避免了指针间接访问的开销
      在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

libai3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值