对象在堆内存中的布局
在HotSpot虚拟机里,对象在堆内存中存储布局可以划分为三个部分:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)。同时对象头又分为对象标记(Mark Word)和类元信息(类型指针)。
对象头(Header)
对象标记Mark Word
默认存储 (哈希值(HashCode )、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳)等信息。这些信息都是与对象自身定义无关的数据,所以MarkWord被设计成一个非固定的数据结构以便在极小的空间内存存储尽量多的数据。它会根据对象的状态复用自己的存储空间,也就是说在运行期间MarkWord里存储的数据会随着锁标志位的变化而变化。在64位系统中,Mark Word占了8个字节,类型指针占了8个字节,一共是16个字节在64位系统中一个对象头,Mark Word占了8个字节,类型指针占了8个字节,一共是16个字节
类元信息(又叫类型指针)
对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
public class TestDemo {
public static void main(String[] args) {
// 类元信息就相当于左边的模版
Customer customer = new Customer();
}
}
class Customer{ //只有一个对象头的实例对象
}
实例数据
存放类的属性(Field)数据信息,包括父类的属性信息。
class Customer{
// 属性
private int id ;
}
对齐填充
虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐。这部分内存按8字节补充对齐。
代码演示
//分析对象在JVM的大小和分布,http://openjdk.java.net/projects/code-tools/jol/
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
代码实例
public class TestDemo {
public static void main(String[] args) {
Customer customer = new Customer();
//System.out.println(VM.current().details());
System.out.println(ClassLayout.parseInstance(customer).toPrintable());
}
}
// 只有对象头,没有实例数据
class Customer{
private int id ;
}
运行结果说明:Customer只有对象头对象标记占8字节,类型指针占4字节,不够对齐填充4字节,构成16字节。下面在Customer 对象中添加属性,在运行
// int + boolean 满足对齐填充 24 bytes
class Customer{
// 4 字节
private int id ;
// 1 字节
private boolean flag =true;
}
原文始发于微信公众号(阿福聊编程):Java对象内存布局和对象头
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/105782.html