讲一讲对象创建流程

对象的创建应该是从jvm执行new指令开始

1.类加载检查,检查是要创建的类是否加载过,如果加载过直接就进入到下一步分配内存

如果未加载则加载过后再分配内存

2.分配内存,在类加载进方法区之后其实就已经可以确定创建这个类对象需要的内存空间大小了,于是根据这个大小在堆(也有可能在栈)上allocate开辟一个指定对象大小的内存

    分配内存首先会判断下是否在栈上分配还是堆上分配,这个就涉及到防逃逸分析,通过判断该对象在该方法中是否会被其他地方(除了当前方法)访问到,举个最简单的例子就是是否有将创建的对象引用返回供方法外部使用,如果有,证明这个对象会逃逸,不能在栈上分配,其实也就是不能随着方法栈帧的出栈而销毁,如果没有,证明这个对象只会在该方法使用,可以通过在栈帧上分配内存随着栈帧的弹出而销毁,栈帧上分配内存又涉及到对象的标量替换,用清楚点的话将就是将对象在堆上的内存分配内容进行简化打散,只是简单的记录对象的属性值,减少一些不必要的信息记录,从而减轻栈分配带来的容量问题.

     如果防逃逸分析没通过,也就是在堆上分配,那么就是在堆上创建指定大小的内存空间,对象在堆中的分配大致分为三大模块,一块是对象头,一块是实例数据,一块是填充对齐,

     首先说明 一下对象头,对象头包括MarkWord,Klass point,数组长度,MarkWord主要是记录对象的一些元数据,包括锁信息,分代年龄等,Klasspoint类型指针指向方法区中对应该对象的类元数据信息的地址,数组长度,只有数组对象才会有,顾名思义就是记录该数组的长度了.

     然后说说一下实例数据,就是对象中成员变量的信息数据了

    最后填充对齐,主要是虚拟机的规范要8字节的整数倍,方便分配而且也是方便读取。

    而堆上又划分为eden区,survivor区1,survivor2及老年代,首先决定分配内存后,会判断下对象内存的大小是否超过指定值,如果超过直接分配你老年代,如果不超过则分配进eden区,分配内存的时候为了不发生多线程并发问题,一般采取两种解决方案,一种是cas,一种是tlab,thread locall allocate buffer,就是为每个线程单独分配一块自己使用分配的内存,就避免了多线程的冲突

    分配内存主要涉及到两种分配方法,一种是指针碰撞,一种是空闲列表,

     指针碰撞就是在堆上会维护一个指针,左边的都是分配好的内存,右边的都是还未分配的内存,当有内存要分配的时候只需要将该指针向右移动对应大小的内存块就可以了

     空闲列表就是维护一张表记录哪些内存空间值空闲,大小是多少,每次需要分配的时候查一下适合大小的内存

     

3.设置零值

就是将对象中的成员变量赋"零值",比如整型类型的0,引用类型的null

4.设置对象头,就是创建对象对应的header object,上文已经提过

5.执行init方法,就是为属性赋值和执行构造方法

 

 

 

       

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值