对象结构、实例化、访问

对象实例化的方式

创建对象的方式

1.new:直接new,或者单例模式中调用类内部的静态方法(类内自己new),或者xxxbuilder,xxxFactory(本质都是new)

2.Class的newInstance() 或者 Constructor 的newInstance(可带参数)前者已过时,被后者替代

3.clone(),不调用任何构造器,需要接口Cloneable的clone()方法

4.反序列化:从文件、网络中获取对象的二进制流。

5.第三方库

创建过程(字节码角度)

先加载到方法区,在堆内创建对象,栈里存放对象的引用

具体创建过程

1.判断这个类是否被加载

虚拟机遇到new指令,检查元空间常量池是否有这个类的符号引用,并检查他是否被加载、链接、初始化。如果没有加载,双亲委派机制,如果没有找到.class,那么报ClassNotFoundException

2.分配内存

先计算对象的大小,然后判断内存是否规整

如果规整:

指针碰撞(把用过的内存放一边,没用过的放一边,中间放一个指针,分配内存时,指针向空闲那边移动对象大小的距离)

如果不规整:使用空闲列表

内存空间是碎片的,虚拟机维护一个列表,记录哪些内存是可用的,再找出足够大的空间给对象分配,并更新表,这种方式叫“空闲列表

3.处理并发安全问题

采用CAS失败重试、区域加锁保证更新的原子性

每个线程分配TLAB

4.初始化分配到的空间

所有属性设置默认值,保证对象实例字段在不赋值的时候可以直接使用

5.设置对象头
6.执行init方法初始化

属性显式初始化,代码块中初始化,构造器中初始化

对象的结构

对象头,实例数据,对齐填充

对象头
  • 普通对象对象头(64bit):
    • ​ 运行时元数据(Mark Word 32bit):哈希值,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳
    • 类型指针(Klass Word 32bit):指向元空间中的类元数据InstanceKlass,确定类的类型。
  • 数组对象对象头(96bit):
    • 比普通对象多个数组长度(array length 32bit)
实例数据

包括程序代码中定义的各种类型的字段(包括父类继承的)

规则:相同宽度的字段总是被分配在一起

​ 父类定义的变量会出现在子类之前

​ 如果COmpactFields参数为true,子类的窄变量可能插入到父类变量的空隙。

对齐填充

占位符,不用看。

对象访问定位

jvm如何通过栈帧的引用访问对象实例的呢

直接指针(Hotspot):栈帧中的引用记录了对象实例的地址,对象实例中的对象类型指针指向方法区的类型数据。
句柄访问:栈帧引用指向句柄池,句柄池就是堆中的指针,指向对象实例和对象类型。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值