java对象的内存布局为:对象头(Header),实例数据(Instance Data),对齐填充(Padding)。
对象头:
对象头包括两部分:
- 第一个部分用于存储对象自身的运行时数据;第二个部分用于存储指向对象所属类元数据的指针。 第一部分:在32位和64位的虚拟机上长度分别为4bytes和8bytes(未开启压缩指针,注:压缩指针现在我也不是很了解,但是随着对象了解认识的深入,这个内容也会掌握),存储哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等。
- 第二部分:首先一点,并非所有虚拟机实现都在对象头里保留这个指向类型的指针,也就是说,查找对象元数据信息不一定要经由对象本身(可通过堆中句柄池里的指针指向元数据),如果对象是一个数组,那么对象头里还需要有一块用于记录数组的长度的数据。
实例数据:
对象真正存储的有效信息,各种类型的字段内容。另附各类型字段占用内存大小:
primitive type | memory required(bytes) |
---|---|
boolean | 1 |
byte | 1 |
char | 2 |
short | 2 |
int | 4 |
float | 4 |
long | 8 |
double | 8 |
reference类型在32位系统上每个占用4bytes, 在64位系统上每个占用8bytes。
对齐填充:
HotSpot VM的自动内存管理系统要求对象起始地址必须是8bytes的整数倍,就是对象的大小必须是8字节的整数倍。对象头是8字节的整数倍,所以当实例数据部分没有对齐时,需通过对齐填充来补全。
最后,附一篇关于对象实际占用内存的计算及复合对象占用总内存的计算的文章,作者写的深入浅出,很好懂~
地址:[java对象内存占用计算实例]