java对象中的内存布局
在虚拟机中,一个对象在堆内存中的存储可以分为三个部分:对象头(Header),实例对象(Instance Data)和对齐填充(Padding).下面我们就来了解一个这三个部分分别是什么,以及它们的作用.
1.对象头
对象头又分为两个部分.Mark Word 和 Klass Word(不要怀疑,就是Klass,不是class).它们在不同的JVM中大小占比也是不同的.下文默认JVM为HotSpot虚拟机32位.
概述 | 32位虚拟机 | 64位虚拟机 | |
---|---|---|---|
Mark Word | 存储对象运行时数据 | 32bit | 64bit |
Klass Word | 类型指针,指向对象的类型元数据 | 32bit | 64bit |
Array Lenght(数组对象独有) | 数据的长度 | 32bit | 64bit |
1 Mark Word
MarkWord 主要是用于存储对象本身的运行时数据:哈希码(HashCode),GC分代年龄(age),锁信息等.对象需要存储的运行时数据有很多,如果都存储起来就会超过32位.考虑到虚拟机的空间效率,MarkWord被设计成一个有着动态定义的数据结构.既一个对象的MarkWord会根据不同的状态来存储不同的数据.下面是几种情况.
|-------------------------------------------------------------|--------------------|
| Mark Word (32 bits) | State |
|-------------------------------------------------------------|--------------------|
| identity_hashcode:25 | age:4 | biased_lock:1(0)| lock:2(01) | Normal |
|-------------------------------------------------------------|--------------------|
| thread:23 | epoch:2 | age:4 | biased_lock:1(1) | lock:2(01)| Biased |
|-------------------------------------------------------------|--------------------|
| ptr_to_lock_record:30 | lock:2(00) | Lightweight Locked |
|-------------------------------------------------------------|--------------------|
| ptr_to_heavyweight_monitor:30 | lock:2(10) | Heavyweight Locked |
|-------------------------------------------------------------|--------------------|
| | lock:2(11) | Marked for GC |
|-------------------------------------------------------------|--------------------|
后面的()中的内容代表在该特定状况下的二级制值,比如lock在Normal状况下占两位,值为(01)
下面对其中的数据进行解释.
- identity_hashcode:对象的HashCode,事实上,如果一个对象没有调用hashCode()方法,那么这个对象的identity_hashcode的值就是0.
- age:java对象的GC分代年龄.
- biased_lock:对象是否开启偏向锁.1代表开启偏向锁.
- lcok:锁的状态标志.有表格可知,当 biased_lock为0,lock为01时,对象为无锁状态.lock为00时,代表为重量级锁.10为轻量级锁.11位GC标志
- ptr_to_lock_record:指向该对象的锁的线程的lock_record
- ptr_to_heavyweight_monitor:指向该对象的Monitor指针.
1.2Klass Pointer
类型指针,一个对象通过该指针就可以知道该对象是哪个类的实例.
1.3Array Length
记录数组的长度.但是如果一个数组的对象的长度是不确定的,那么将无法通过元数据中的信息推断出数组的大小
2.实例数据(Instance Data)
实例部分数据则是对象中存储的真正有效的信息,既程序员设定的各类属性值.
3.对齐填充(Padding)
这部分内容不是必须存在的,也没有什么特殊含义,但是由于HotSpot虚拟机规定对象的起始地址必须是8字节(32位).对象的对象头一定是8字节的整数倍.所以如果实例部分的不是整数倍就要加上一点占位符来达到要求.