Java对象创建、内部数据、如何访问(HotSpot虚拟机下)

前言

对象创建:查找类型,确认类加载,分配内存,初始化内存,设置对象,init🖊

对象构造:对象头(Markword,类型指针),实例数据

对象访问定位:从栈上的引用访问到对象,需要查找到堆中的对象,然后通过对象中的类型指针找到其类型

对象创建过程

这里讲的是普通的Java对象,不包括数组或Class对象

  1. 虚拟机遇到new指令时,检查指令参数是否能在常量池中定位到这个类的符号引用
  2. 检查这个符号引用代表的类是否已经被加载、解析和初始化
  3. 若未加载,执行相应的类加载过程
  4. 为新生对象分配内存。需要内存大小在编译时就可完全确定。分配方式有几种,“空闲列表”、“指针碰撞”、“CAS+失败重试保证原子性”,“分配TLAB本地线程分配缓冲”
  5. 内存空间初始化零值。这一步保证了对象的实例字段在不赋初始值就可以直接使用,能访问到队形数据类型所对应的零值
  6. 虚拟机对对象进行设置。例如是哪个类、对象哈希码、GC分代年龄、是否设置偏向锁等,对对象头Object Header设置。
  7. 执行init方法,按照程序员意愿初始化对象。这样才算是真正被完全生产出来对象(在这之前对象内都还是零值)

对象的内存布局

  • 对象头:MarkWord+类型指针
    • MarkWord:对象自身运行时的设置数据:哈希码HashCode,GC分代年龄,锁状态,持有锁,偏向线程ID等
    • 类型指针:指向类元数据,虚拟机通过这个指针确定对象的类型
  • 实例数据:包括对象定义的数据,而且还包括从父类继承的、子类定义的数据
  • 对齐填充:补位的无意义填充

对象访问定位

Java程序是如何通过引用定位到对象实例数据和类型数据的?

虚拟机有两钟可实现的方式:

  • 句柄方式:Java堆中划分出一个句柄池,其中每个句柄存放对象实例数据和类型数据各自的地址信息。特点是稳定,对象被移动只改变句柄不改变reference。
  • 直接指针:Java堆的对象还存放一个类型的指针。速度更快,节省了1次指针定位的时间开销。(这正是HotSpot虚拟机的实现方式)

通过句柄访问对象

通过类型指针访问对象

本文标题:Java对象创建、内部数据、如何访问(HotSpot虚拟机下)

文章作者:Aaron.H

发布时间:2018年07月21日 - 19:07

最后更新:2018年09月07日 - 08:09

原始链接:https://uncleaaron.github.io/Blog/Java/Java对象-HotSpot虚拟机下/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。