一、内存分配策略
1.1 指针碰撞
顺序分配,分配与未分配之间添加一个指针,每次分配时,指针往后移动需要的空间即可
优点:操作简单
缺点:要求堆空间要规整;多线程下效率不高
1.2 空闲列表
按需分配,需要一张表记录分配情况
优点:需要一个列表做存储
缺点:产生了空间碎片问题,大对象存入时会出现无连续空间问题
二、对象在堆中的存储布局
在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:
2.1 对象头
2.1.1 Mark Word
存储对象自身的运行时数据:哈 希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。
使用Mark Word(一个有着动态定义的数据结构)做存储:
所占位数:32(64)位操作系统中是32(64)位;如对象未被同步锁锁定的状态下,Mark Word的32个比特存储空间中的25个比特用于存储对象哈希码,4个比特用于存储对象分代年龄,2个比特用于存储锁标志位,1个比特固定为0。在其他状态(轻量级锁定、重量级锁定、GC标记、可偏向)下对象的存储内容如表所示
2.1.2 类型指针
对象指向它的类型元数据(类)的指针,Java虚拟机通过这个指针来确定该对象是哪个类的实例。并不是所有的虚拟机实现都必须在对象数据上保留类型指针,换句话说,查找对象的元数据信息并不一定要经过对象本身。
2.1.3 数组对象需要这部分
如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通 Java对象的元数据信息确定Java对象的大小,但是如果数组的长度是不确定的,将无法通过元数据中的 信息推断出数组的大小。
2.2 实例数据
是对象真正存储的有效信息,即我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的字段都必须记录起来。
2.3 对齐填充
这并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。
由于HotSpot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是任何对象的大小都必须是8字节的整数倍。对象头部分已经被精心设计成正好是8字节的倍数(1倍或者 2倍),因此,如果对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。