对象在堆内存的存储布局,可分为对象头、实例数据和对⻬填充。
1、对象头
占 12B,包括对象标记和类型指针。
======= 🌟 青柠来相伴,代码更简单。🌟 =======
📚 本文所有内容,我都整理在了 青柠合集 里。👇
🎯 搜索关注【青柠代码录】,即可查看所有合集文章 ~
======= 🌟 ================== 🌟 =======
对象标记
存储对象⾃身的运⾏时数据,如哈希值、 GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,这部分占8B,称为Mark Word。
Mark Word (64 bits) State
--------------------------------------------------------------------------------
unused:25 | hashcode:31 | age:4 | biased_lock:0 | 01 Normal
--------------------------------------------------------------------------------
thread:54 | epoch:2 | age:4 | biased_lock:1 | 01 Biased
--------------------------------------------------------------------------------
ptr_to_lock_record:62 | 00 Lightweight Locked
--------------------------------------------------------------------------------
ptr_to_heavyweight_monitor:62 | 10 Heavyweight Locked
--------------------------------------------------------------------------------
| 11 Marked for GC
对象状态
【无锁状态】:对象哈希值---GC分代年龄---是否是偏向锁---锁标志位 【偏向锁】:偏向线程ID---epoch---GC分代年龄---是否是偏向锁---锁标志位 【轻量级锁】:指向栈中锁记录的指针---锁标志位 【重量级锁】:指向互斥量(重量级锁/monitor)的指针---锁标志 【GC标记】:空
Mark Word 被设计为动态数据结构,以便在极⼩的空间,存储更多数据,根据对象状态,复⽤存储空间。
类型指针
是对象指向它的类型元数据的指针,占 4B。
JVM 通过该指针,来确定对象是哪个类的实例。
说明:如果是数组,还需记录数组的长度
2、实例数据
是对象真正存储的有效信息,即本类对象的实例成员变量,和所有可⻅的⽗类成员变量。
存储顺序会受到虚拟机分配策略参数,和字段在源码中定义顺序的影响。
相同宽度的字段总是被分配到⼀起存放,在满⾜该前提条件的情况下,⽗类中定义的变量,会出现在⼦类之前。
3、对⻬填充
不是必然存在的,也没特别含义,仅起占位符作⽤。
虚拟机的⾃动内存管理系统,要求任何对象的⼤⼩必须是8B的倍数,对象头已被设为 8B 的 1 或 2 倍,如果对象实例数据部分没有对⻬,需要对⻬填充补全。
public class CustomerTest {
public static void main(String[] args) {
Customer cust = new Customer();
}
}

此处字符串常量池逻辑上属于方法区,hotspot实现在堆空间中
