在 深入理解JVM运行时内存结构 中,我们宏观地探讨了 JVM 运行时的内存布局。本文将深入分析每个内存区域的细节。由于不同虚拟机的内存管理实现不同,具体的讨论需要聚焦于特定虚拟机和内存区域。基于实用优先的原则,我们以最常用的 HotSpot 虚拟机和 Java 堆内存为例,深入探讨在 HotSpot 虚拟机里:
- 对象在堆内存中是如何布局的?
- JVM 是如何实现 Java 对象?
- 对象是如何创建出来的?
对象的内存布局
在虚拟机里,对象由三部分构成,分别是 对象头、实例数据、对齐填充。对象头的结构复杂,下面会详细介绍。实例数据是对象真正存储的有效信息,包含所有我们在代码中定义的各种类型的字段的内容,无论是继承自父类还是在子类中定义的。最后是对齐填充,由于HotSpot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是任何对象的大小都必须是8字节的整数倍。对象头部分已经被精心设计成正好是8字节的倍数,如果对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。
接下来,我们详细说说对象头。HotSpot 虚拟机对象的对象头由三部分构成,分别是存储对象自身运行时数据的 Mark Word、指向类型元数据的指针、当对象是数组时,记录数组长度的 length。在 64 位系统中,对象头的大小是 16 个字节,可以通过指针压缩的方式,压缩到 12 个字节。当 JVM 中存在大量对象的时候,通过指针压缩减少对象内存占用是一个提升性能的手段。
需要注意的是,并不是所有虚拟机在实现对象时,都会在对象头中保留类型指针,还可以通过其它方式来查找对象类型的元数据信息,这点会在最后的「对象的访问」小节中补充讨论。