jvm学习笔记2--对象的产生

6 篇文章 0 订阅

提出问题

在java的世界中,我们频繁的会使用对象。创建一个对象对我们而言,就是一行代码:

	User user = new User("hello world");

在这行代码的背后,jvm都做了哪些工作呢?学习总结下。

对象创建过程

当jvm在执行字节码指令的时候,遇到一条字节码new指令的时候,做以如图所示的以下工作:
在这里插入图片描述

检查常量池

先去检查下这个指定的参数在常量池中是否可以定位到一个类的符号引用,并且要去检查这个符号引用所代表的类是否已经被加载、解析和初始化过。有的话,就直接引用;没有的话就要执行下一步。

执行类加载

类加载过程细节后面填坑,这块比较复杂。

给对象分配内存

类加载检查之后,虚拟机要给新生成的对象分配内存。对象所需内存大小在类加载完成后就完全确定了 如何确定的后面再填坑。

给对象分配内存,就是在java堆中把一块确定大小的内存区域划分出来。分配的方式有2种:

  • 指针碰撞:假设java堆中的内存都是绝对规整的,所有使用过的或者被分配的在一遍,空闲内存放在另一边,中间放一个指针作为分界点。那本次的内存分配就是把指针从当前位置向空闲的方向移动一段与对象大小相等的距离,这种方式叫做指针碰撞
  • 空闲列表:如果java堆不是规整的,已被使用的内存和未被分配的空闲内存相互交错放在一起,那就没有办法使用指针碰撞的方式了,就需要维护一个列表,记录哪些内存区域是可用的。在分配的时候从可用的区域中找到一块足够大的划分给当前对象实例,并更新列表记录,这种方式叫做空闲列表

在划分可用空间给对象的时候,需要考虑一个问题:创建对象、给对象分配内存在虚拟机中是非常高频的行为,仅仅修改指针的位置,在并发情况下也不是线程安全的操作,可能出现在给A对象分配的内存,指针还没有修改,B对象也在基于原来的指针分配内存的情况。解决这种问题就有2种方案:

  • 采用CAS+失败重试来保证更新操作的原子性
  • 将内存分配的动作按照线程划分到不同的空间中进行,即每个线程提前先分配到一小块内存,称为本地线程分配缓冲(TLAB),哪个线程要分配内存,就在自己的分配缓冲中进行,本地缓冲用完了再采用方案1同步锁定分配

初始化分配的内存空间

jvm将分配到的内存空间都初始化成零值,如果采用了TLAB的方案,这一步可以提前至TLAB分配时进行。这步操作保证对象的实例字段在java代码中可以不赋初始值就能直接使用

设置对象

jvm需要对对象进行必要的设置,比如对象是哪个类的实例、如何找到类的元信息、对象的哈希码、对象的GC分代年龄等。这些信息都存放在对象的对象头中。具体的设置后面详细介绍

对象构造

上面的所有流程完成之后,一个新的对象就产生了。接下来,就要开始对这个新的对象进行构造了。只有按照业务场景给对象初始化,一个真正的对象才算是构造完成。

总结

一行代码,jvm就帮我们做了这么多事情。
还有很多的细节没有一一描述,后面每个步骤深挖的时候再完善。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值