对象的创建

读《深入理解Java虚拟机》

Java是一门面向对象的编程语言,在Java程序运行过程中每时每刻都有对象被创建出来。在语言层面上,创建对象只是一个new关键字,在虚拟机中,对象(普通的java对象,不包括数组和Class对象)的创建是怎样的?这里简单的概述一下。

1. 加载

当虚拟机遇到一条new指令时,首先去建仓这个指令的参数是否能在常量池中定位到一个类的引用,并检查这个符合的引用的类是否已被加载,解析初始化,如果没有,则必须先执行相应的类加载过程。

2. 分配内存

当类加载通过后,虚拟机将会为新对象分配内存。对象所需的内存大小在类加载完成后即可完全确定,为对象分配内存等同于在堆中把一块确定大小的内存划分出来。

  • 假设堆中的内存是完全规整的,所有用过的内存放在一边,空闲的内存放另一边,中间放着一个指针作为分界点。那分配内存只是将指针向空闲的那边挪动一段与对象大小相等的距离,这种方式称为“指针碰撞”。

  • 假设堆中的内存不是完全规整的,那虚拟机就必须维护一个列表,记录哪些内存是可用的,在分配内存的时候从列表中找到一块足够大的空间划分给对象,并更新列表的记录,这种方式称为“空闲列表”。

选择哪种方式取决于内存是否规整,而内存是否规整取决于垃圾收集器是否带有压缩整理功能。

3. 对象创建时多线程问题

对象在虚拟机中的创建是非常频繁的过程,分配内存在多线程下是不安全的。解决方案有两种。

  • 采用CAS配上失败重试机制保证更新操作的原子性
  • 把内存分配按照线程划分在不同的空间中进行,即每个线程在堆中预先分配一块内存,成为本地线程缓冲区(TLAB,线程私有,在堆中)。哪个线程要分配内存,就在那个线程的TLAB中分配,只有TLAB用完并分配新的TLAB时,才需要同步锁定,给这个线程再分配一块内存。
4. 内存空间初始化

内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头)。这步操作可以保证对象的实例在java代码不赋初值的情况下可以直接使用,访问到这些字段对应的零值。

5. 对对象进行一些必要的设置

虚拟机要对对象进行一些必要的设置。例如这个对象是哪个类的实例,对象的哈希吗,对象的GC分代年龄等信息。这些信息都存放在对象的对象头中。

6. init

从虚拟机的角度来看,一个新的对象已经产生了。但是从java程序的角度来看,对象的创建才刚刚开始,init方法还没有执行,所有的字段都是初始零值。执行new指令后会执行init方法,把对象按照程序员的意愿初始化,这样一个真正可用的对象才算完全产生出来。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值