JVM对象的创建过程(通俗易懂)

对象的创建

虚拟机中对象的创建过程:

  1. 对象检查:当Java虚拟机遇到一条字节码new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程

  2. 对象创建:类加载检查通过后,虚拟机为新生对象分配内存。对象所需内存的大小在类加载完成后便可完全确定。(Java堆的内存分配:由于Java堆内存并不规则,已使用的、未使用的内存交杂在一起,没有办法简单进行“指针碰撞”,虚拟机必须维护一个列表,记录那些内存块可用。分配时就从列表中找到一块足够大的空间划分给对象实例,并更行列表记录。————“空闲列表(Free List)”

  3. 内存分配:对象创建完毕后,虚拟机必须将分配到的内存空间都初始化为零值。保证了实例字段在Java代码中不实例化就直接使用,使程序能访问到这些字段的数据类型所对应的零值。

  4. 对象设置:例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码(实际上对象的哈希码会延后到真正调用Object::hashCode()方法时才计算)、对象的GC分代年龄等信息。这些信息存放在对象的对象头(Object Header)之中。

注意:

对象创建在虚拟机是非常频繁的行为,在并发情况下线程并不安全。例如:正在给对象 A分配内存,指针还没来得及修改,对象B又同时使用了原来的指针来分配内存的情况。解决方案:

  1. 对分配内存空间的动作进行同步处理
  2. 把内存分配的动作按照线程划分在不同的空间之中进 行,即每个线程在Java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB),哪个线程要分配内存,就在哪个线程的本地缓冲区中分配,只有本地缓冲区用完 了,分配新的缓存区时才需要同步锁定。

        在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了。但是从Java程序的视角看来,对象创建才刚刚开始——构造函数,即Class文件中的<init>()方法还没有执行,所有的字段都为默认的零值,对象需要的其他资源和状态信息也还没有按照预定的意图构造好。一般来说,new指令结束后会接着执行init()方法,按照程序员的意愿对程序进行初始化,这样一个对象才被构建出来。

对象的内存布局

大多数程序员用的都是HotSpot,因为在Oracle官网下载的jdk里面带的就是这款虚拟机。

在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头(Header)实例 数据(Instance Data)对齐填充(Padding)

        例如在32位的HotSpot虚拟机中,如对象未被同步锁锁定的状态下,Mark Word的32个比特存储空间中的25个比特用于存储对象哈希码,4个比特用于存储对象分代年龄,2个比特用于存储锁标志位,1个比特固定为0。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值