java对象实例化,内存布局以及访问定位

本文详细探讨了Java中创建对象的多种方式,包括new、反射、克隆、反序列化等,并解析了对象创建的步骤,如内存分配、初始化和对象头设置。同时,介绍了对象的内存布局,包括对象头、实例数据和对齐填充。此外,还讨论了对象访问定位的两种方式:句柄池和直接指针,分析了各自的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建对象的几种方式

    1.new对象,相信大家最常用的就是这个
      存在两种变形
      1.类的静态方法,例如单例模式
      2.builder以及factory方法
    2.Class的newInstance():反射的方式,但是只能使用空参构造器,权限也必须是pubilc
    3.Constructor的newInstance(XXX):依然是反射的方式,可以调用有参的构造器,权限没有限制
    4.使用反序列化:从文件或者网络中获取对象的二进制流
    5.clone:类需要实现Cloneable接口,实现clone()方法
    6.第三方库

创建对象的步骤

    1. 判断对象是否加载,链接,初始化
    2. 为对象分配内存【指针碰撞/空闲列表】
    3. 处理并发安全问题【采用cas/为每个线程分配自己的TLAB】
    4. 初始化分配到的空间【变量默认值初始化,例如int默认值0,boolean默认值false等】
    5. 设置对象头【类元信息/hashcode和对象的GC信息以及锁信息,具体设置方式取决于jvm】
    6. 调用init方法进行初始化

对象的内存布局

对象头
    1.运行时元数据
       1.哈希值
       2.GC分代年龄
       3.所状态标示
       4.线程持有的锁
       5.偏向线程ID
       6.偏向时间戳
    2.类型指针:指向类元信息确定该对象所属类型
    如果记录的是数据还需要记录一下数组的长度
实例数据
   对象真正存储的有效信息,包括程序代码中定义的各种类型的字段(包括从父类继承下来的和本身拥有的)
   相同宽度的对象总是被分配在一起,父类中定义的变量会出现在子类之前,如果CompactFields参数设置为true则子类的窄变量可以穿插到父类变量的空隙
对齐填充
   不是必须的也没有特定含义,仅仅起到占位符的作用。

对象的访问定位方式

句柄池
  句柄池是栈帧中的引用指向一个句柄池,句柄池中包括指向堆空间实例的指针以及一个指向方法区类型的指针。
  优点是当GC后对象的位置发生了变化的话栈中的引用不需要发生变化因为句柄池的地址是没有发生变化的
  缺点就是多了一次指针查找需要的性能损耗
直接指针
与句柄池对应,直接指针是栈中的引用指向堆中的实例,实例中存在一个指向方法区中对象类型的指针。
优点是节省了一次指针定位的时间开销
缺点是当GC后对象的地址发生了变化的话栈中引用所存储的地址也会发生变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值