JVM学习之对象的实例化、内存布局、访问定位

发布于:2022-11-28 ⋅ 阅读:(244) ⋅ 点赞:(0)

对象的实例化;对象的创建方式 创建对象的步骤

创建对象的六个步骤:

  • 判断对象对应的类是否加载、链接、初始化

  • 为对象分配内存:

如果内存规整->指针碰撞:

如果内存不规整->虚拟机需要维护一个列表,进行空闲列表分配

       具体选择哪种分配方式由java堆是否规整,而java堆是否规整又由所采取的垃圾收集器是否带有压缩整理功能决定。

  • 处理并发安全问题

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

       每个线程预先分配一个TLAB,通过-XX:+/-UseTLAB参数来设定

  • 初始化分配到的空间:对对象的属性默认初始化(赋默认初始化值)
  • 设置对象的对象头

  • 执行init方法进行初始化(显示初始化、代码块初始化、构造器中初始化)

对象的内存布局:对象头、实例数据、对齐填充

  • 对象头:主要包含两部分,运行时元数据和类型指针

运行时元数据:

  • 哈希值
  • GC分代年龄
  • 锁状态标志
  • 线程持有的锁
  • 偏向线程ID
  • 偏向时间戳

类型指针:指向类元数据InstanceKlass,确定该对象所属的类型

注:如果创建的是数组,还需要记录数组的长度

  • 实例数据:它是对象真正存储的有效信息,包括程序代码中定义的各种类型的字段(包括从父类继承下来的和本身拥有的字段)

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

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

         如果CompactFields参数为true(默认为true),子类的窄变量可能插入到父类变量的空隙

  • 对齐填充:不是必须的,也没什么特殊含义,仅仅起到占位符的作用

举例:Customer cust=new Customer();内存布局图:

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

图示:

  • 访问对象的方式:句柄访问、直接指针

       句柄访问:

       直接指针:

句柄访问、直接指针访问优缺点:

句柄访问需要单独开辟句柄池,浪费空间,且访问时需要经过句柄池访问类元信息和对象实例数据,访问效率较慢。

句柄访问的优点:在栈中维护的reference地址比较稳定,

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到