原文:https://www.cnblogs.com/zhi-leaf/p/11589711.html
虚拟机:Java HotSpot™ 64-Bit Server VM
对象的内存以字节为单位,必须是8的倍数,它的构成由3部分组成:对象头+实例数据+对齐内存。对象头主要包括对象的运行行元数据,比较哈希码、GC分代年龄、锁状态标志还有类型指针,类型指针指向类元数据,表明该对象所属类型。实例数据包括自身数据和所有父级数据,所有父级占内存大小都是8的倍数,没有就需要补齐。类型指针一般为4字节,在关闭压缩普通对象指针时(-XX:+UseCompressedOops)为8字节,UseCompressedOops默认是开启的,只有虚拟机内存达到32G以上,4个字节已经无法满足寻址需求时,才需要关闭该参数。
普通对象头除类型指针外的大小为8字节,在开启压缩总大小为12字节,不开启压缩总大小为16字节;数组对象头在开启压缩时是16字节,不开启压缩为24字节。
各种类型大小如下:
对象类型 字节
boolean 1
byte 1
short 2
char 2
int 4
float 4
long 8
double 8
引用类型 开启指针压缩为4,不开启为8
普通对象头 开启指针压缩为12,不开启为8
数据对象头 开启指针压缩为16,不开启为24
例1:
public class Persion {
int id;
}
开启压缩普通对象指针时,对象大小:(8+4)+4+0=16字节,补齐0字节
关闭压缩普通对象指针时,对象大小:(8+8)+4+4=24字节,补齐4字节
例2:
public class Persion {
int id;
String name;
int age;
Date birthday;
}
开启压缩普通对象指针时,对象大小:(8+4)+(4+4+4+4)+4=32字节,补齐了4字节。
关闭压缩普通对象指针时,对象大小:(8+8)+(4+8+4+8)+0=40字节,补齐了0字节
例3:
public class Persion {
int id;
String name;
int age;
Date birthday;
boolean school;
}
public class Student extends Persion {
int b;
}
开启压缩普通对象指针时:
Person对象的大小为:(8+4)+(4+4+4+4+1)+7=32字节,补齐了7字节。
Student对象的大小为:(8+4)+(4+(4+4+4+4+1+7)) +0=40字节,Person对象补齐了7字节。
关闭压缩普通对象指针时:
Person对象的大小为:(8+8)+(4+8+4+8+1)+7=48字节,补齐7字节
Student对象的大小为:(8+8)+(4+(4+8+4+8+1+7))+4=56字节,Person对象补齐了7字节,Student补齐4字节。
class MyList {
Persion[] elementData = new Persion[10];
}
开启压缩普通对象指针时:
MyList对象大小:(8+4)+4+0=16字节,补齐了0字节
new Person[10]数组对象大小:16+4*10+0=56字节,补齐了0字节
关闭压缩普通对象指针时:
MyList对象大小:(8+8)+8+0=24字节,补齐了0字节
new Person[10]数组对象大小:24+8*10+0=104字节,补齐了0字节
例5:
@SuppressWarnings("serial")
class MyArrayList extends ArrayList<Persion> {
}
AarryList和它父级只有3个非静态成员变量(size为整数、elementData为数组引用,在ArrayList类中,modCount为整数在AbstractList类中),静态变量内存在堆的另外部分,不在对象内。
开启压缩普通对象指针时:
MyArrayList对象大小:(8+4)+(0+(4+4+(4+4)))+4=32字节,AbstractList做了一次补齐,整体做了一次补齐。(与下图结果不符,后面抽时间在看看)
关闭压缩普通对象指针时:
MyArrayList对象大小:(8+8)+(0+(4+8+(4+4)+4))+0=40字节,AbstractList做了一次补齐,ArrayList做了一次补齐