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

JVM-对象实例化内存布局与访问定位

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

JVM-对象实例化内存布局与访问定位

创建对象的步骤

1 、检查类是否加载、链接、初始化

检查类是否已经被加载,解析和初始化
如果没有,那么在双亲委派模式下,使用当前类加载器以ClassLoader + 包名 + 类名为key进行查找对应的 .class文件

  • 如果没有找到文件,则抛出ClassNotFoundException异常,
  • 如果找到,则进行类加载,并生成对应的Class对象。
2、为对象分配内存

有两种分配方式:指针碰撞法和空闲列表分配
选择哪种分配方式由Java堆是否规整所决定,而Java堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
如果堆内存是规则的,则采用指针碰撞的内存分配方式。
堆内存不规整的采用空闲列表法。

  • 指针碰撞法
    如果内存是规整的,那么虚拟机采用指针碰撞法来为对象分配内存。
    所有用过的内存在一边,空闲的内存放另外一边,中间放着一个指针作为分界点的指示器,分配内存时,仅需要把指针往空闲那边挪动一段与对象大小相等的距离即可。

  • 空闲列表分配
    如果内存不是规整的,已使用的内存和未使用的内存相互交错,那么虚拟机将采用的是空闲列表来为对象分配内存。
    意思是虚拟机维护了一个列表,记录哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的内容。

3、处理并发安全问题
  • 采用CAS失败重试和区域加锁,保证指针更新操作的原子性
  • 为每个线程预先分配好TLAB(本地线程分配缓冲区)
4、初始化分配到的内存

为对象分配完堆内存之后,JVM会将该内存进行零值初始化

5、 设置对象的对象头

将对象的所属类(即类的元数据信息)、对象的HashCode和对象的GC信息、锁信息等数据存储在对象的对象头中。

6、 执行init方法进行初始化

初始化顺序如下:

至此,一个真正可用的对象才算完成创建出来

对象的内存布局

class  Customer{
int id;
Account acc; //Account 类
}

Customer类定义了id和类Account 两个属性

Customer c=new Customer();

现在new一个Customer对象,内存布局如下图:

对象的访问定位

JVM是如何通过栈帧中的对象引用访问到其内部的对象实例呢?

对象访问的两种方式 句柄访问

句柄访问就是在栈的局部变量表中,记录对象的引用,然后在堆空间中开辟了一块空间,也就是句柄池。

优点
reference中存储稳定句柄地址,对象被移动(垃圾收集时移动对象很普遍)时只用改变句柄中实例数据指针即可,reference本身不需要被修改

直接指针访问

直接指针是局部变量表中的引用,直接指向堆中的实例,在对象实例中有类型指针,指向的是方法区中的对象类型数据,

缺点是reference本身会随着对象被移动而修改

但整体性能更优,所以hotspot采用直接指针访问的方式

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

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

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