对象的内存布局
- 头对象(Header)
- 实例数据(Instance Data)
- 对齐填充(Padding)
文章图片
头对象 头对象记录了对象在运行过程中所需要使用的一些数据:
- 哈希码
- GC分代年龄
- 锁状态标志
- 线程持有的锁
- 偏向的线程ID
- 偏向的时间戳
实例数据 实例数据部分就是成员变量的值,其中包括父类成员和本类成员变量。
对齐填充 用于确保对象的总长度为8字节的数据倍。
HotSpot VM 的自动内存管理系统要求对象的大小必须是8字节的整数倍。而对象头部分正好是8字节的倍数(1倍或2倍),因此,当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。
对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。对象的创建过程 类加载检查
虚拟机在解析
.class
文件时,若遇到一条new指令,首先他会去检查常量池中是否有这个类的符号引用,并检查这个符号引用所代表的类是已被加载、解析和初始化过。如果没有,如果没有则必须先执行类的加载过程。为新生对象分配内存
对象所需内存的大小在类加载完成后便完全确定,接下来从堆中划分一块对应大小的内存空间给新的对象。分配堆内存有两种方式:
- 指针碰撞
- 空闲列表
初始化
分配完内存以后,为对象成员变量赋上初始值,设置对象头信息,调用对象的构造函数方法进行初始化。
致辞,整个对象的创建过程就完成了。
对象的访问方式 所有对象的存储空间口都是在堆中分配的,但是这个对象的引用确是在Java栈中的本地变量表中分配的。也就是说在创建一个对象时两个地方都分配内存,在堆中分配的内存是实际建立这个对象,
句柄访问方式
堆中需要有一块叫做“句柄池”的内存空间,句柄中包含了对象实例数据与类型数据各自的具体地址信息。
引用类型的变量存放的是该对象的句柄地址(reference)。访问对象时,首先需要通过引用类型的变量找到该对象的句柄,然后根据句柄中对象的地址找到对象。
文章图片
直接指针访问方式
引用类型的变量直接存放对象的地址,从而不需要句柄池,通过引用能够直接访问对象。但对象所在的内存空间需要额外的策略存储对象所属的类信息的地址。
文章图片