java对象在HotSpot虚拟机中的结构
Java对象由三部分组成,对象头、实例数据、填充数据。
对象头
-
markwork
存储对象运行时数据,HashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向锁ID、偏向时间戳等。在64位虚拟机中,如果没有开启压缩指针,占用64bit。
无锁
锁状态 25位 31位 1位 4位 1位(偏向锁位) 2位(锁标志) 无锁 unused hashCode(调用hashCode方法时填充) unused 分代年龄 0 01 偏向锁
锁状态 54位 2位 1位 4位 1位(偏向锁位) 2位(锁标志) 偏向锁 当前线程指针 Epoch unused 分代年龄 1 01 轻量级锁(自旋锁)
锁状态 62位 2位(锁标志) 轻量级锁 指向线程栈中LockRecord的指针(通过自旋竞争锁CAS,有次数上限) 00 重量级锁
锁状态 62位 2位(锁标志) 重量级锁 指向互斥量(重量级锁)的指针 10 -
klass
Class对象指针的大小也是4个字节,其指向的位置是对象对应的Class对象(其对应的元数据对象)的内存地址。
-
数组长度
只有数组对象有数组长度,如果对象为数组,对象头中必须记录数组长度。
对象实际数据
包括了对象的所有成员变量,其大小由各个成员变量的大小决定
填充
填充数据不是必须存在的,没有特别的含义,只是占位,HotSpot中VM内存管理系统要求对象起始地址必须是8字节的整数倍,
即对象大小必须是8字节的整数倍,对象头是8字节的1或2倍。
Java中String类型的大小
String成员变量
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
对象头(未开启压缩指针):8 (Markdown)+ 4(Klass指针)+(8+4+4)(char数组大小) + 4(hash大小)+ 8(serialVersionUID大小) = 40
非空String内存大小
40(空对象大小) + 2(一个char2字节) * n