栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

对象实例化内存布局和访问定位

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

对象实例化内存布局和访问定位

对象实例化的几种方式
  1. new
    1. 变形一:Xxx的静态方法获取(比如说单例模式)
    2. 变形二:XxxBuilder/XxxFactory的静态方法(工厂模式)
  2. Class的newInstance():反射的方式,只能调用空参构造方法,权限必须是public
  3. Constructor的newInstance(Xxx):反射的方式,可以调用空参、有参构造方法,权限没有要求
  4. 使用clone():不调用任何构造器,需要当前类实现Cloneeable接口,实现clone()
  5. 使用反序列化:从文件、网络中获取一个对象的二进制流
  6. 第三方库Objenesis
从字节码看对象的创建步骤
  1. 检查对象对于的类是否加载、链接、初始化(涉及到类的父类的加载)
  2. 给对象分配内存空间:具体使用那种看使用的垃圾收集器所采用的算法
    1. 内存规整:指针碰撞
    2. 内存规整:需要维护一张列表,记录空闲的内存空间。空闲列表分配
  3. 处理并发安全问题
    1. 采用CAS失败重试,区域加锁保证更新的原子性
    2. 每个线程预先分配了一块TLAB
  4. 初始化分配到的空间:对对象的属性进行默认的初始化,设置属性类型的默认初始化值
  5. 设置对象头
  6. 执行方法,显示初始化属性的值
对象内存布局
  1. 对象头
    1. 运行时元数据:如果创建的是一个数组,还要记录数组的长度
      1. 哈希值(HashCode)
      2. GC分代年龄
      3. 锁状态标志
      4. 线程持有的锁
      5. 偏向线程ID
      6. 偏向时间戳
    2. 类型指针:指向类元数据InstanceKlass,确定对象所属的类型
  2. 实例数据
    1. 对象真正存储的有效信息,包括程序代码中定义的各种类型的字段(包括从父类继承下来的和自己本身所拥有的)
    2. 规则
      1. 相同宽度(大小)的字段总是分配到一起
      2. 父类定义的变量会出现在子类之前
      3. 如果CompactFieIds的参数为true(默认为true):子类的窄变量有可能插入到父类变量的空隙
  3. 对齐填充:起到占位符的作用
    1. 由于HotSpot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是任何对象的大小都必须是8字节的整数倍。对象头部分已经被精心设计成正好是8字节的倍数(1倍或者2倍),因此,如果对象实例数据部分没有对齐的话,就需要通过对齐填充来补全

对象的定位访问

有两种方式:句柄访问、直接指针(HotSpot采用)

句柄访问

        局部变量表保存指向堆中的句柄池的地址,由句柄分别指向实例池中的对象实例和方法区中的对象类型数据

直接指针

优缺点:

  1. 句柄访问
    1. 优点:如果对象的地址发送改变(比如空间整理),局部变量表保存的句柄不需要变化
    2. 缺点:占用堆内存空间,并且相对于直接指针多了一步
  2. 直接指针
    1. 优点:不占用堆内存空间,效率比句柄快
    2. 如果对象的地址发送改变,局部变量表中的值需要改变
图释
 再补一张JVM内存布局

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/821395.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号