对象头
在我们常用的
Hotspot
虚拟机中,对象在内存中布局实际包含
3
个部分:
- 对象头
- 实例数据
- 对齐填充
而对象头包含两部分内容,
Mark Word
中的内容会随着锁标志位而发生变化,所以只说存储结构就好了。
- 对象自身运行时所需的数据,也被称为Mark Word,也就是用于轻量级锁和偏向锁的关键点。具体的内容包含对象的hashcode、分代年龄、轻量级锁指针、重量级锁指针、GC标记、偏向锁线程ID、偏向锁时间戳。
- 存储类型指针,也就是指向类的元数据的指针,通过这个指针才能确定对象是属于哪个类的实例。
如果是数组的话,则还包含了数组的长度。
指针碰撞
一般情况下,
JVM
的对象都放在堆内存中(发生逃逸分析除外)。当类加载检查通过后,
Java
虚拟机开始为新生对象分配内存。如果Java
堆中内存是绝对规整的,所有被使用过的的内存都被放到一边,空闲的内存放到另外一边,中间放着一个指针作为分界点的指示器,所分配内存仅仅是把那个指针向空闲空间方向挪动一段与对象大小相等的实例,这种分配方式就是 指针碰撞。
空闲列表
如果
Java
堆内存中的内存并不是规整的,已被使用的内存和空闲的内存相互交错在一起,不可以进行指针碰撞啦,虚拟机必须维护一个列表,记录哪些内存是可用的,在分配的时候从列表找到一块大的空间分配给对象实例,并更新列表上的记录,这种分配方式就是空闲列表。
TLAB
可以把内存分配的动作按照线程划分在不同的空间之中进行,每个线程在
Java
堆中预先分配一小块内存,
这就是
TLAB
(
Thread Local Allocation Buffer
,本地线程分配缓存) 。虚拟机通过
-XX:UseTLAB 设定它的。