对象创建、布局、访问相关内容

在了解java内存区域以后,需要进一步了解对象是如何在堆中创建,分配内存以及如何进行定位访问。由于不同虚拟机对对象的操作存在差别,这里选取常用虚拟机hotspot中对象进行分析。

1.对象如何创建?

在语言层面上,对象的创建常见方式是new关键字进行创建,(当然,还有通过反射、反序列化、克隆),那么在jvm内部,jvm碰到new指令以后在内部是如何操作的?

jvm碰到new指令执行流程:

  1. 检查指令参数能否在方法区常量池中定位到一个符号引用。如果无法定位到一个符号引用,说明这个类没有定义,将抛出ClassNotFoundException
  2. 检查这个符号引用所对应的类有没有被加载,解析和初始化。如果没有,需要执行加载过程。
  3. 在类已被加载,解析、初始化以后,需要在堆中为新生对象分配内存。对象在类加载以后,由类生产的对象大小即可确定。

    在堆中分配对象空间的方法:

    • 指针碰撞法:java堆属于规整状态,已用堆内存在一侧,空闲堆内存在另一侧,中间通过指针分割并划分内存,当有新生对象到来时,通过移动指针给新生对象划分特定大小的内存。
      这种方法要求java堆必须处于规整状态。
      这里写图片描述
    • 空闲列表法:堆内存可以不规整,此时需要通过一个空闲列表记录在堆内存中存在的空间空间。当有新生代对象到来时,通过查看空闲列表,找到适合对象大小的内存空间,将空间分配给该对象,并修改空闲列表。
      这种方法需要划出额外的空间用于维护空闲列表。

    对象采用何种分配算法,取决于jvm采用何种垃圾回收算法,标记清除算法适合采用空闲列表,而标记整理,复制算法适合于指针碰撞法。

  4. 为对象中的成员变量赋上默认初始值
  5. 设置对象头信息,对象是属于哪个类的实例,对象的哈希码,对象的GC分代年龄等
  6. 调用对象的构造函数进行初始化。

    对象完成构建

2.对象在内存中的布局?

上面描述了对象如何在内存中是如何创建的,下面将讨论对象在内存中的结构。为什么hash查找速度最快,与对象在内存中的结构是否有关;进行垃圾回收时,jvm如何确定该对象是否可回收,在经历几次标记之后,标记信息是存储在哪里,这些是否与对象在内存中的布局有关;多线程中,对对象进行加锁,锁信息保存在哪里,与对象结构是否有关?

在hotspot虚拟机中,对象在内存中的布局分为三个部分:对象头、实例数据、对齐;
这里写图片描述

下面对每一部分进行描述:

  1. 对象头
    存储对象在运行中需要用到的数据:哈希码、GC分代年龄、锁状态标志、线程持有的锁、线程偏向ID、偏向时间戳等;
    类型指针:对象指向其类元数据的指针,虚拟机通过这个指针确定这个对象是哪个类的实例(查找类元数据不一定要经过对象本身,如下面所说的句柄池);
    如果对象是数组,对象头中还有一块区域用于保存数组大小;

  2. 实例数据
    存放的是对象各种类型字段的值,包括父类成员变量,子类成员变量

  3. 对齐填充
    hotspot vm要求对象起始地址必须是8字节的整数倍,所以要保证一个对象所占的内存是8的整数倍,由于对象头正好是8的整数倍,所以通过填充实例数据使其成为8字节的整数倍,使对象对齐。

3.对象如何访问定位?

通过上面我们知道对象在堆内存中的布局,那么,在运行过程中,虚拟机栈中的引用是如何定位到堆中的对象?是虚拟机栈中的引用存储的即是对象在堆中的内存地址,还是引用存储的是一个中间介质,通过中间介质再去访问对象。

在jvm中有俩种对象定位方式,一种是句柄访问,一种是直接地址访问

  1. 句柄访问
    java堆中划分出一块内存作为句柄池,虚拟机栈中存储的是对象的句柄地址,句柄中包含了对象的实例地址和元数据地址。
    访问对象时,先根据对象引用找到句柄池地址,再根据句柄池中的对象数据地址找到对象。
    这里写图片描述

  2. 直接地址访问
    虚拟机栈中的引用存储的是对象在堆内存中的地址,通过该地址直接定位到对象,不需要经过中间媒介,更加快速,但是在对象的内存结构中需要存储对象的类型指针,用于定位方法区的对象类型。
    这里写图片描述

直接地址访问比句柄访问快一倍,因为它只需要一次寻址操作,但它在对象内存结构中需要额外存储类型指针。hotspot采用的对象访问方式就是直接地址访问。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值