对象的内存布局
对象的组成
在HotSpot虚拟机中,对象在内存中的分配的区域,可以划分成三个模块
- 对象头 对象头主要包含两部分数据,标记字段(Mark Word)、类型指针(Class Pointer).如果是数组还包括数组长度,不是数组就没有这部分内容。
- 实例数据 包括了对象的所有成员变量,大小由各变量类型决定,包括基本类型和引用类型,这是对象真正存储的有效信息。
- 对齐填充 由于虚拟机要求对象起始地址必须是8字节的整数倍,那么当对象大小不是8的整数倍的时候,会填充一部分内容,直到内存大小等于8的整数倍。其存在的意义就是为了字节对齐。
对象头和Monitor的关系
Mark Word
Mark Word用于存储对象自身的运行信息.Java对象头以一字宽来存储Mark Word信息。
在32位虚拟机中,一字宽等于4字节。在64位虚拟机中,1字宽等于64bit.
运行期间,Mark Word的数据类型会随着锁标志位的改变而改变,一共有以下几种状态:无锁、偏向锁、轻量级锁、重量级锁、和可回收(GC标志)
synchronized加锁时,如果是重量级锁,那么Mark Word中的指针就指向了Monitor的地址。
由于互斥锁的线程切换开销太大,所有后来java引入了 轻量级锁和偏向锁。适用于线程竞争不激烈的时候使用。JVM可以通过参数 -XX:UseBiasedLocking。
如果不开启偏向锁,那么刚刚创建的对象,Mark Word中存锁标志位为01,Mark Word中存储的对象是对象的hash code ;如果开启了偏向锁,那么刚创建的对象,锁状态就是偏向锁状态,线程id为0,标识尚未有线程获取,不偏向任何线程;偏向锁被线程获取以后,Mark Word就存储线程id.
开启偏向锁的JVM,随着线程竞争的升级,会将偏向锁升级为轻量级锁,再进一步膨胀为重量级锁。对象的Mark Word中的数据和锁标志位也会随之改变。
如果一个对象被标记了GC标志,那么这个对象即将被垃圾回收。Mark Word中的数据自然就空了。