Java 对象创建过程


提示:以下是本篇文章正文内容,下面案例可供参考

一、Java 对象创建的过程?

在这里插入图片描述

  1. 类的加载检查
    当虚拟机遇到一条new 指令时,先会根据指令的参数去常量池中看一下是否能定位到这个类的符号引用,并且检查这个类代表的符号引用是否已被加载过、解析和初始化过。如果不是,则必须先执行相应的类加载过程。

  2. 分配内存
    当类加载检查通过后,接下来虚拟机将为新生对象分配内存,对象所需的内存大小在类加载完毕后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从Java 堆中划分出来,分配方式有 “指针碰撞”,和 " 空闲列表" 两种,选择哪种分配方式是由Java堆是否规整来决定的,而Java堆是否规整是由垃圾收集器是否具有压缩整理的功能来决定的。
    内存分配的两种:

    1. 指针碰撞
      适用场合:堆内存规整(即没有内存碎片)的情况下
      原理:用过的内存放到一边,没有用过的内存放到另一边,中间有一个分界指针,只需要指针向着空闲内存的方向移动对象内存大小的空间即可
      使用该分配方式的GC收集器有:Serial 、 ParNew
    2. 空闲列表
      适用场合:堆内存不规整的情况下
      原理:虚拟机会维护一个列表,该列表中会记录哪些内存块是可用的,在分配的时候找一块足够大的内存块分给对象实例,最后更新列表记录
      使用该分配方式的GC有:CMS

    内存分配并发问题(补充内容,需要掌握)

在创建对象的时候有一个很重要的问题,就是线程安全,因为在实际开发过程中,创建对象是很频繁的事情,作为虚拟机来说,必须要保证线程是安全的,通常来讲,虚拟机采用两种方式来保证线程安全:
CAS+失败重试: CAS 是乐观锁的一种实现方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性。
TLAB: 为每一个线程预先在 Eden 区分配一块儿内存,JVM 在给线程中的对象分配内存时,首先在 TLAB 分配,当对象大于 TLAB 中的剩余内存或 TLAB 的内存已用尽时,再采用上述的 CAS 进行内存分

  1. 初始化零值
    在内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段在Java 代码中不赋初始值就直接使用,程序能访问到这些数据字段所对应的零值。

  2. 设置对象头
    初始化零值完成之后,虚拟机需要给对象进行必要的设置,例如这个对象是哪个类的实例,如何才能找到类的原数据信息、对象的哈希码、对象的GC分带年龄。这些信息存放在对象头中。另外根据虚拟机运行状态的不同,是否启用偏向锁等,虚拟机会有不同的设置。

  3. 执行init 方法
    上述步骤执行完成后,从虚拟机的角度来看,一个新的对象已经产生,但是从Java 程序来看,对象创建才刚开始,init 方法还没有执行。所有的字段都还为 0,所以一般来说,执行new 指令之后紧接着执行init 方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才能完全生成出来

猜你喜欢

转载自blog.csdn.net/CXgeng/article/details/124204274