从虚拟机角度看对象的创建

(1)当JVM遇到一个new指令的时候,他会去检查这个指令的参数能否在运行时常量池定位到一个类的符号引用,并且检查这个符号代表的类是否已经被加载,解析和初始化过了,如果没有,那么必须先执行相应的类加载过程。
(2)在类的加载检查通过之后,接下来JVM需要为新生对象分配内存,对象所需的内存大小是在类加载完成之后便完全确定的。如果Java堆是规整的,那么直接采用指针碰撞算法分配内存(记录上一次对象分配的位置,当有新对象需要分配时,若检查剩余的空间可以满足容纳这个对象,则只需要一次移动指针的操作便可完成内存的的分配),否则使用空闲列表算法(这需要JVM维护一个列表,记录哪些内存块是可以使用的,在分配的时候分配一块足够大的内存块给对象)。内存是否规整取决于垃圾收集器是否具有压缩整理功能。在使用Serial,ParNew等带有压缩过程的收集器的时候,采用的是指针碰撞算法。而使用CMS这类使用标记-清除算法的垃圾收集器来说,使用的是空闲列表算法。

对于多线程的应用:内存分配需要保证线程安全,如果通过全局锁的方式来保证线程安全的话,内存分配将会成为性能瓶颈。所以HotSpot采用线程局部分配缓冲技术(TLAB),每一个线程都拥有自己的TLAB,位于Eden区中的一小块空间(TLAB的平均大小一般限制在Eden区的1%以下)。因为每一个TLAB是仅对一个线程可见的,所以分配操作可以采用指针碰撞技术快速完成,而不需要任何锁机制,只有在线程将TLAB填满并且需要获得一个新的TLAB的时候,同步才是必须的。在开启UseTLAB选项的前提下,在分配一个新的对象空间的时候,将首先在TLAB中分配对象空间,若分配空间请求失败,再尝试使用加锁机制在Eden区分配空间。

(3)内存分配完成之后,需要将分配的内存空间都初始化为零值(不包括对象头),如果使用了TLAB,那么这一过程可以提前到TLAB分配的时候进行。这一步操作可以保证对象的实例字段在java代码中可以不赋初值就可以使用。
(4)接下来,JVM需要对对象进行必要的设置,比如这个对象是哪个类的实例,如何快速找到类的元数据信息,对象的哈希码,对象的GC分代等信息。这些信息都是放在对象的对象头(Object Header)之中。根据当前JVM的运行状态的不同,如是否使用偏向锁等,对象头会有不同的设置方式。
(5)当上面的工作完成之后,从JVM角度来看,一个新的对象已经生成,但是从程序角度来看,对象创建才刚刚开始—方法还没有执行,所有的字段都是0。所以在new之后,一般都会接着执行方法,按照程序员的意愿进行初始化,这样一个真正的对象才被创建出来。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值