在 HotSpot虚拟机中,对象在内存中存储的布局分为三块区域:对象头,实例数据,和对齐填充。java
对象头包括以下两部分信息:数组
MarkWord:用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。为了在极小空间内存储更多的信息,它被设计成了一个非固定的数据结构,根据对象的状态来复用本身的存储空间,以下:数据结构
存储内容 | 标志位 | 状态 |
---|---|---|
对象哈希码、分代年龄 | 01 | 未锁定 |
指向锁记录的指针 | 00 | 轻量级锁定 |
指向重量级锁的指针 | 10 | 膨胀(重量级锁定) |
空 | 11 | GC标记 |
偏向线程ID\偏向时间戳、分代年龄 | 01 | 可偏向 |
类型指针:到对象类型数据的指针,即虚拟机经过这个指针来肯定这个对象属于哪一个类。(有的虚拟机经过句柄池来实现)框架
若是对象是一个数组:对象头还须要有一块空间来记录数组长度,由于对象能够经过类型指针判断Java对象大小,而数组不行。布局
是对象真正的有效数据,也就是代码中所定义的各类类型的字段内容,不管是从父类继承仍是子类记录的都必须进行存储。ui
对齐填充并非必然存在的,也没有其它的意义,仅仅是占位符的做用,由于HotSpot虚拟机的自动内存管理系统要求对象地址必须是8的整数倍,当实例数据没有对齐时,就须要对齐填充来进行补齐。线程
当咱们使用对象时,咱们须要经过虚拟机栈上的reference数据(即worker)来操做堆上的具体对象。设计
public Worker buildWorker(){ Worker woker = new Woker(); worker.setAge(21); .... return worker; }
访问具体对象的方式不一样虚拟机有不一样的实现,主流的方式有如下两种指针
在Java堆中专门划分处一部份内存做句柄池,reference中存储的是对应对象的句柄地址,而句柄池中包含了对象实例数据和类型数据具体的地址信息,以下图:code
直接指针访问,reference中直接存储对象地址。