java 对象内存布局
面试题:初始化创建的对象有多大?
答案: 16字节
Object a = new Object(); 16字节
String[] b = new String[2](); 16字节 / 24字节
对象的内存布局
主体内容包括:
- 对象头: MarkWord、指针、数字长度(数组对象才有)
- 数据体: 对象的数据,初始化一般为 空
- 数据对齐:要求对象大小,为8的倍数,而做的特殊设置
普通对象
- 对象头:包括 :markWord + 指针
- markword 为8个字节
- classPointer 指针:指向对应的 class的指针,一般为 8个字节,如果开启“ -XX:+UseCompressedClassPointers”,则压缩为 4个字节。
- 实际数据:成员变量 和 引用类型
- 对齐 padding :(填充作用,使对象的字节永远为 8的倍数。如果对象实际为 15个字节,对齐后,会填补一个字节。)
new Object() 的大小为 16.
- MarkWord为 8个字节,指针(Class Pointer)压缩情况下为4个字节。实体数据内容为0个,padding 操作(对齐)。最后结果为16个。
- MarkWord为 8个字节,指针(Class Pointer)不压缩情况下为8个字节。实体数据内容为0个,padding 操作(对齐)。最后结果为16个。
数组对象
- 对象头:markword + classPointer 指针
- 数组长度 :数组长度 为 4个字节
- 数组数据
- 对齐 padding
new int[];
- MarkWord为 8个字节,指针(Class Pointer)压缩情况下为4个字节,数组长度为 4个字节。实体数据内容为0个,padding 操作(对齐)。最后结果为16个。
- MarkWord为 8个字节,指针(Class Pointer)不压缩情况下为8个字节,数组长度为 4个字节。实体数据内容为0个,padding 操作(对齐)。最后结果为24个。
对象头都会包什么信息
第一个 锁的信息,代表对象有没有被锁定
第二个 GC 标记,对账被GC标记的分代年龄
java 引用对象的方法有几种
2种。
- 句柄池法(间接指针):存在一个句柄池,记录所有对象的地址。引用对象时,从句柄池中找对象地址,并引用
- 直接指针法:通过对象头的指针,找到对象地址。
JVM 是使用直接指针法~~ !!!!
为什么要对齐为8的倍数
假设我们使用64位操作系统,也就是说,一次寻址(读取)64个二进制位,也就是 8字节的寻址空间。换句话说,系统一次读取8个字节的内容。
常识: 一个字节为8个二进制位。
简单举例:
boolean、int、char想要获取,都是读取一次就行,读取前半部分就可以。但如果想读取long需要读取两次,才能得到结果。
所以添加了对齐操作。
就是这么简单,从而提升性能的。