对象在内存中的存储布局可以用下面的图来标识
对象在内存的存储布局主要包含四个部分markword,class pointer,instancs date,padding
其中markword占8个字节这个是固定的,只要你的电脑是64位的这个就是64位占8个字节
class pointer 代表是的类型指针也就是指向的是这个对象是什么类型的数据如果开启了压缩指针那么就是4个字节,没有开启 的话就是8个字节
instance data 代表的是你的对象中包含的成员变量
padding 这个主要是用于补齐,因为你的一个对象生成的字节最后要被8整除所以如果上面的3个部分生成的字节数如果不能被8整除,那么就靠padding这个来补充相应的字节数来达到8的倍数
至于为啥对象的字节数一定要是8的倍数,那是因为cpu在读内存中的值的时候是按照总线的宽度来读的,如果对象的字节数被8整除的话,那么jvm在读的时候会特别顺,特别快,是为了提高效律
但是为了避免伪共享问题,JVM 会按照 8 个字节的倍数进行填充,所以会填充 4 个字
节变成 16 个字节长度。
其中对象头的部门包含markword 和classpointer部分,而其中的markword主要包含三大信息,锁信息,hashcode,GC
我们可以使用一个JOL(JAVA OBJECT LAYOUT)来查看一个对象在内存中的存储布局
引入依赖
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
实体类
public class User {
private String userid;
private String username;
private String tid;
}
方法调用
public class Test {
public static void main(String[] args) throws ParseException {
User user=new User();
System.out.println(ClassLayout.parseInstance(user).toPrintable());
}
}
输出结果
输出的结果中前两行数据markword属于八个字节,第三行数据classpointer占四个字节,然后紧接着的三行属于实体类的三个String属性每一个占用四个字节,所以说new User对象总共占用24个字节
如果给User对象新增一个int类型的变量结果如下
如果说只是创建一个对象里面没有任何属性值那么将会占用16个字节
byte 1字节
short 2字节
int 4字节
long 8字节
char 2字节(C语言中是1字节)可以存储一个汉字
float 4字节
double 8字节
boolean false/true(理论上占用1bit,1/8字节,实际处理按1byte处理)
引用(reference):4 个字节
上面的String因为没有赋值就是一个引用所以占四个字节