Java 对象的创建过程小结

对象的创建过程(5步):

1.类加载检查-->2.分配内存-->3.初始化零值-->4.设置对象头-->5.执行init方法

  • 1.类加载检查

虚拟机遇到一条new指令时,先检查这个指令的参数能否在常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,则先进行类的加载过程。

  • 2.分配内存

在类加载检查完成后,接下来虚拟机为新生对象分配内存。对象所需内存的大小在类加载完成后便可完全确定,为对象分配空间的任务等同于把一块确定的内存从java堆中划分出来。主要有两种方式:

1)假设Java堆中的内存是规整的,用过的内存在一边,空闲的在另一边,中间有一个指针作为分界点的指示器,所分配的内存就把那个指针向空闲那边挪动一段与对象大小相等的距离。

注:jvm将堆区抽象为两块区域,一块是已经被其他对象占用的区域,另一块是空白区域,中间通过一个指针进行标注,这时只需要将指针向空白区域移动相应大小空间,就完成了内存的分配

问题:要求虚拟机的对内存是地址连续的,且虚拟机带有内存压缩机制。多线程创建对象时,会导致指针划分不一致的问题,例如A线程刚刚将指针移动到新位置,但是B线程之前读取到的是指针之前的位置,这样划分内存时就出现不一致的问题

2)如果Java堆中的内存不是规整的,虚拟机必须维护一个列表,记录哪些内存块可用的,分配时从列表中找到一块足够大的空间划分给对象,并更新列表的记录。

注:由于堆内存是线程共享区域,如果多线程同时为对象分配内存,则上述方法必然存在线程安全问题。通常可想到的方案是对内存分配动作进行同步加锁处理,但这种方式必然影响效率;另一种方案为采用TLAB(Thread Local Allocation Buffer)方式,即先为每个线程分配一块内存,然后哪个线程需要为对象分配内存时,就在各个线程的内存区域内部分配,这也可以保证各个线程间互不影响。当TLAB空间用完重新分配时,才需要同步处理。

  • 3.初始化零值

将分配到的内存空间都初始化为零值,如果用TLAB,则在TLAB分配时初始化为零值。

  • 4.设置对象头

主要是存储一些信息,如此对象属于哪个类、怎么样获取类的元数据、对象的hashcode、对象的GC分代年龄等信息,这些信息存放在对象的对象头中(对象在内存中的存储布局分为3个区域:对象头、实例数据、对齐填充)。

  • 5.执行init方法

此时,从虚拟机角度看,新的对象已经产生,但从java程序角度看,对象创建才刚开始,执行new指令后会接着执行方法,把对象按照程序员的意向进行初始化,这样一个真正可用的对象才算完全产生出来。

 

参考博客:

https://blog.csdn.net/ahence/article/details/77993768

https://blog.csdn.net/linda_lindaaaa/article/details/88726026

https://blog.csdn.net/BX666666/article/details/104713911

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值