记一次对java对象在内存中的分析
java 对象 占内存大小 计算方式 及 常用类型的占用
HotSpot的对齐方式为8字节对齐
计算公式:
1 (对象头 + 实例数据 + padding) % 8 = 0 2 // 0 <= padding < 8
对象头的内存布局
1Byte = 8bit,而cpu一次能处理的数据位数是32位和64位也就是4字节和8字节
对象自身的运行数据 占一次cpu
指向对象实例的指针 占 一次cpu
数组比较特殊,因为要把数据长度存到头部,所以又要占 一次cpu
以上可以看出普通对象的对象头有两部分而数组对象有三部分,可以推算出 :
32 位:引用类型 4字节
|-- 普通对象:对象头 8字节
|-- 数组对象:对象头 12字节;增加元素时,增加引用,则+4B,增加基本数据类型,则+基本数据类型的长度
64 位:引用类型 8字节
|--普通对象:对象头 16字节
|--数组对象:对象头 24字节;增加元素时,增加引用,则+8B,增加基本数据类型,则+基本数据类型的长度
从JDK 1.6 update14开始,64 bit JVM正式支持了 -XX:+UseCompressedOops 这个可以压缩指针,起到节约内存占用的新参数。
启用CompressOops后,会压缩的对象:
• 每个Class的属性指针(静态成员变量)
• 每个对象的属性指针
• 普通对象数组的每个元素指针
当然,压缩也不是万能的,针对一些特殊类型的指针,JVM是不会优化的。
比如指向PermGen的Class对象指针,本地变量,堆栈元素,入参,返回值,NULL指针不会被压缩。
压缩后
64位压缩后:引用类型 4字节
|--普通对象:对象头 12字节
|--数组对象:对象头 16字节;增加元素时,增加引用,则+4B,增加基本数据类型,则+基本数据类型的长度
----因为 java 的跨平台性,所以基本类型的数据在32位和64位上占内存大小是一样的
数据类型 | 内存占用 |
byte | 1字节 |
short | 2字节 |
int | 4字节 |
long | 8字节 |
float | 4字节 |
double | 8字节 |
char | 2字节 |
boolean | 1字节 |
数据类型 | 引用类型 | 对象头 | ||
32位 | 64位 | 32位 | 64位 | |
普通对象 | 4字节 | 8字节 | 8字节 |
16字节 |
数组对象 | 4字节 | 8字节 | 12字节 | 24字节 |
如有理解不当或建议,欢迎指正