文章目录
1、对象的构成
对象的构成主要是由对象头(header),实例数据(instance data),对齐填充(保证8字节的倍数) 组成的
他们的分布关系主要如下图所示 , 下面我会对他们的组成部门进行一一的讲解;
1.1、对象头(header)
对象头主要包括对象标记 (markWord),类元信息(类型指针) , 当我们声明一个类时(没有变量),此时他就是一个对象头
//只有一个对象头
class MyClass{
}
1.1.1、对象标记 (markWord)
问题1:对象标记主要保存什么?
它主要保存了对象的hashCode,锁指针,对象的分代年龄记录
问题2:他占用多大的字节?
在64位系统中,MarkWord占用了8个字节
1.1.2、类元信息(类型指针)
问题1:类元信息主要保存什么?
类元信息存储的是指向对象类元数据的首地址,下面的2点
- Customer的Klass类信息
- Account的Klass类元信息
问题2:类元信息占用多大的字节?
在64位系统中,MarkWord占用了8个字节
问题2:类元信息有什么用?
对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
1.2、实例数据(instance data)
下面的代码就是有了实例数据的类
//有属性了; 有对象头,还有实例数据
class MyClass{
private String id;
}
它存放的是存放类的属性数据信息,包括父类的属性信息;
1.3、对齐填充(保证8字节的倍数)
虚拟机要求对象起始地址必须是8字节的整数倍,填充数据不是必须存在的,仅仅是为了字节对齐这部分内存按8字节补充对齐。
在下面的代码案例: 对象头16字节+int 4 字节 + boolean 1字节 = 21字节; 因为对齐填充,(保证8字节的倍数
)最后得到是24字节;
//有对象头,还有实例数据
class MyClass{
//int 32位 4字节
private int id;
//boolean 1字节
private Boolean flag;
}
2、Object o = new Object 证明
2.1.1、JOL证明
本次证明使用JOL(java object layout)证明 (分析对象在JVM的大小和分布) 观察对象的再JVM内存情况;
POM依赖
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
demo示例
public class ReferenceDemo {
public static void main(String[] args) throws InterruptedException {
//vm的细节详细情况
System.out.println(VM.current().details());
//所有对象分配的字节都是8的整数倍
System.out.println(VM.current().objectAlignment());
}
}
证明:
在这里有个疑问:为什么类型指针是4字节的?主要是他下面的开启了压缩指针;继续观看下节;
2.2.1、压缩指针
开启压缩指针了,会对填充字节造成一定影响;
步骤一:开启参数,开启了那些参数, 全部列出来
java -XX:+PrintCommandLineFlags -version
步骤二:
最后我们可以知道本次标题的问题答案,
- 默认开启了压缩,如果开启了压缩,则对象头12字节+对齐填充4字节 = 16字节;如果关闭了压缩,则直接为对象头16字节