首先,我们知道的是每一种数据类型所占用的字节数。比如Integer占用4个字节,Long占用8个字节等。但是实际我们在创建对象的时候,在JVM中的占用的字节数是比这个高的。
一个对象在JVM中的内存布局包含以下内容:
- 对象头(Header): 对象头包含两类信息,第一类是用于存储对象自身的运行时数据,如哈希吗,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID等。 如果JVM是64位,则这部分占用 8个字节,如果JVM是32位,这部分占用4个字节。另外一部分是类型指针,对象指向它的类型源数据指针, JVM通过这个指针来确定对象是哪个类的实例。这部分占用内存的大小和JVM是否开启指针压缩的属性有关,开启 CompressedOops则该数据指针占用内存是 4 位,如果没有开启,就是8位。下面的计算都是按照开启。
- 实例数据: 这部分就是对象真正的有效信息。 Long占用8个字节,int占用4个字节等。
- 对齐填充(padding):占位符的作用,因为HotSpot虚拟机的自动内存管理系统要求对象的起始地址必须是8字节的整数倍,所以不满8位的数据,会自动补充。所以对象的内存占用都是8的倍数。
关于数组(如char[], int[])
数组的对象头占用空间在原有的对象头上需要多加一个,就是存放数组长度的,占用4个字节。所以一个空的数据,占用的内存是 16个字节。
关于String
上面是String的类信息,首先String这个类占用内存大小是 8(对象头)+ 4(指针)
内部包含char[] : 内存大小 8(对象头)+ 4 (指针)+ 4(长度存放)
包含int : 内存大小 4
包含long: 内存大小是 8
所以一个new String(“”)的对象占用内存大小是40 字节。
在char[] 数组中,一个char占用的是2个字节。
综上,一个String类型的数据,在内存中占用的大小是 40 + 2* length
附上图:
另外使用Java代码是可以计算出一个对象的占用内存大小的。点击跳转