大家可能遇到过Object o = new Object(),在内存中占用多少空间。
这里可以使用JOL工具类打印对象头。具体使用方法问度娘
这里首先要了解java内存对象的布局:markword、指针类型 、实例数据(Instance Data)和对齐填充(Padding)。无论是32位还是64位的HotSpot,使用的都是8字节对齐。也就是说每个java对象,占用的字节数都是8的整数倍。
注意:对象头(Header) = markword+指针类型
markword |
类型指针(class pointer) |
实例数据(instance data) |
对齐(padding) |
我们在cmd窗口中输入命令java -XX:+PrintCommandLineFlags -version,如下图
可以看出Jvm是64位,指针长度也就是8Bytes.
UseCompressedClassPointers:压缩指针,默认把指针压缩成4个字节
UseCompressedOops:普通对象指针。例如String a = new String() , 栈中变量a指向堆中new String()的对象指针,这里也是被默认压缩成4B
所以我们默认开启压缩的情况下,new 出来的对象头占用是markword(8)+class pointer(4) = 12个字节。相反,未开启压缩则是8+8 =16个字节。
1.基本数据类型占用的字节数,JVM规范中有明确的规定,无论是在32位还是64位的虚拟机,占用的内存大小是相同的。
原生类型 | 内存占用空间(bytes) |
boolean | 1 |
byte | 1 |
short | 2 |
char | 2 |
int | 4 |
float | 4 |
long | 8 |
double | 8 |
对象头 | 32位(jvm) | 64位(jvm) 关闭-XX:-UseCompressedOops指针压缩 | 64位(jvm) 开启XX:+UseCompressedOops)指针压缩 |
reference类型 | 4Bytes | 8B | 4B |
new Object类型 | 8B | 16B | 12B |
Array类型 | 24B | 16B |
2.对象内存布局中的实例数据,不包括类的static字段的大小,因为static字段是属于类的,被该类的所有对象共享。
现在在来回答开始的问题:如果是64位jvm上开启指针压缩,new Object对象头占用了 16B,不需要padding。
Double[] d = new Double[3] 对象占用多少空间?
我们先来计算64位系统未开启指针压缩的new Double[0]占用空间
1.首先它是数组对象,对象头占用空间是24B
2.数组长度是3, 包装类型Double占用的空间是8B
结果24+3*8 = 48,是8的倍数,不需要Padding,所以最后得出 64位系统未开启指针压缩占用空间是 48B。
根据上面的知识,我们来计算下面这个对象占用的内存空间
public class User{
int a ;
String b ;
}
开启默认压缩的情况
1. new的对象头占用空间 = markword(8)+ class pointer(4) = 12B
2. 基本类型 a 占用空间 = 4B
3.String类型普通指针(开启了压缩) = 4B
4.在padding 4个字节 可以被8整除
所以最终占用24个字节
这里也有篇不错的文章,大家可以看看