8.对象内存布局
对象内存布局
对象内存布局
对象内部结构分为:对象头、实例数据、对齐填充(保证8个字节的倍数)。
对象头
对象头分为对象标记( markOop)和类元信息(Klass0op),类元信息存储的是指向该对象类元数据(Klass)的首地址。
对象标记
默认存储对象的HashCode、分代年龄和锁标志位等信息。这些信息都是与对象自身定义无关的数据,所以MarkWord被设计成一个非固定的数据结构以便在极小的空间内存存储尽量多的数据。它会根据对象的状态复用自己的存储空间,也就是说在运行期间MarkWord里存储的数据会随着锁标志位的变化而变化。
Hotspot 虚拟机对象头Mark Word
存储内容 | 标志位 | 状态 |
---|---|---|
对象hash码、对象分代年龄 | 01 | 未锁定 |
指向锁记录的指针 | 00 | 轻量级锁定 |
指向重量级锁的指针 | 10 | 膨胀(重量级锁定) |
空,不需要记录信息 | 11 | GC标记 |
偏向线程ID、偏向时间戳、对象分代年龄 | 01 | 可偏向 |
在64位系统中,对象标记占8个字节,类型指针占了8个字节,一共是16字节
64位虚拟机存储结构
因为GC分代年龄为4bit -》 1111 所以gc最大年龄为15
JOL代码演示
import org.openjdk.jol.info.ClassLayout; public class ObjectLayoutDemo { public static void main(String[] args) { // 祖宗类 System.out.println("################################祖宗类########################################"); Object o = new Object(); System.out.println(ClassLayout.parseInstance(o).toPrintable()); // 只有类 System.out.println("################################只有类########################################"); Customer customer = new Customer(); System.out.println(ClassLayout.parseInstance(customer).toPrintable()); // 有类有属性 System.out.println("##############################有类有属性#######################################"); Consumer consumer = new Consumer(); System.out.println(ClassLayout.parseInstance(consumer).toPrintable()); } } class Customer { } class Consumer { int id; boolean flag = false; } ################################祖宗类######################################## java.lang.Object object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243) 12 4 (loss due to the next object alignment) (对齐填充) Instance size: 16 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total ################################只有类######################################## Customer object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) d4 cb 00 f8 (11010100 11001011 00000000 11111000) (-134165548) 12 4 (loss due to the next object alignment) Instance size: 16 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total ##############################有类有属性####################################### Consumer object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 12 cc 00 f8 (00010010 11001100 00000000 11111000) (-134165486) 12 4 int Consumer.id 0 16 1 boolean Consumer.flag false 17 7 (loss due to the next object alignment) Instance size: 24 bytes Space losses: 0 bytes internal + 7 bytes external = 7 bytes total #OFFSET 偏移量,也就是到这个字段位置所占用的byte数 #SIZE 后面类型的字节大小 #TYPE 是Class中定义的类型 #DESCRIPTION DESCRIPTION是类型的描述 #VALUE VALUE是TYPE在内存中的值
类元信息(类型指针)
类模板信息
实例数据
存放类的属性(Field)数据信息,包括父类的属性信息
对齐填充
虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐这部分内存按8字节补充对齐。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· DeepSeek “源神”启动!「GitHub 热点速览」
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器