共计 1098 个字符,预计需要花费 3 分钟才能阅读完成。
前言
上一章节带着大家初探 JVM 的类加载机制,以及双亲委派机制, 本文次要介绍了 Java 对象头的组成以及详解
一、一个对象如何组成的?
对象在内存中的布局蕴含: 对象头
、Mark Word
、Klass Pointer
- Mark Word : 用于存储对象本身的运行时数据,如哈希码(HashCode)、GC 分代年龄、锁状态标记、线程持有的锁、偏差线程 ID、偏差工夫戳等
- Klass Pointer:对象指向它的类的元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
- 实例属性 :定义类中的成员属性
- 对齐填充 : 因为 HotSpot 虚拟机的主动内存管理系统要求对象的起始地址必须是 8 字节的整数倍,也就是对象的大小必须是 8 字节的整数倍
二、根本类型占用的字节和位数
根本类型 | 字节 | 位数 |
---|---|---|
byte | 1 byte | 8 bit |
char | 2 byte | 16 bit |
int | 4 byte | 32 bit |
short | 2 byte | 16 bit |
long | 8 byte | 64 bit |
double | 8 byte | 64 bit |
float | 4 byte | 32 bit |
三、new 一个对象占用多少字节
public class Demo1 {public static void main(String[] args) {LockObject lockObject = new LockObject();
System.out.println(ClassLayout.parseInstance(lockObject).toPrintable());
}
static class LockObject{
int a = 4;
long b = 1;
boolean c = false;
}
}
依据下面根本类型占用的字节和位数可计算出:
在开启了指针压缩的状况下:
- 对象头 12 个字节
- 实例数据 int a=4 4 个字节,long b=1 8 个字节,boolean c=false 1 个字节
- 对齐补充 7 个字节。
- 总共 32 个字节
四、对象内存中 offset 作用
offset:绝对于类对象所占内存区域起始地位的偏移
五、对象头详解
- 哈希值 :31 位的对象标识 hashCode,采纳提早加载技术。它是一个地址,用于栈对堆空间中对象的援用指向
- GC 分代年龄(占 4 位):记录幸存者区对象被 GC 之后的年龄 age,个别 age 为 15(阈值为 15 的起因是因为 age 只有 4 位最大就能够将阈值设置 15)
- 锁状态标记 (占 2 位):记录一些加锁的信息
偏差锁标识位 | 锁标记位 | 锁状态 | 存储内容 |
---|---|---|---|
0 | 01 | 未锁定 | hash code(31), 年龄 (4) |
1 | 01 | 偏差锁 | 线程 ID(54), 工夫戳 (2), 年龄 (4) |
无 | 00 | 轻量级锁 | 栈中锁记录的指针 (64) |
无 | 10 | 重量级锁 | monitor 的指针 (64) |
无 | 11 | GC 标记 | 空,不须要记录信息 |
总结
本文次要介绍了 Java 对象头的组成以及详解
正文完