本文共 1013 字,大约阅读时间需要 3 分钟。
本篇内容来自《深入理解Java虚拟机_JVM高级特性与最佳实践》,感谢作者。
创建对象之后需要使用对象,java中除了对对象属性方法的调用以外还有加锁实现同步等其他操作,这里的锁加在了哪里,如何记录锁,如何对锁进行分类(有对象锁,class锁),垃圾回收机制中有关于GC的标记,知道当前对象分代的年龄,这些都需要我们去探寻对象具体的内存布局。
HotSpot虚拟机中对象存储分成三块区域,对象头(Header),实例数据(Instance Data),对齐填充(Padding)。
对象头:对象头记录对象的信息,包括哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向时间戳,类型指针。
实例数据:存储对象自身定义的数据
对齐填充:为了对齐填充的额外数据。
从上面对象各个区域存储的信息可以看到对象头存储了对象的主要描述信息。
对象头分成两部分:
(1)Mark Work 存储对象运行时数据
哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等,这部分长度在32和64位虚拟机中分贝占32bit和64bit。对象头记录了与对象自身定义的数据无关的额外存储成本,所以Mark Word被设计成非固定的数据结构以便在极小的存储空间存储尽量更多的信息。
对象哈希码、对象分代年龄 标志位 01 未被锁定
指向锁记录的指针 标志位 00 轻量级锁定
指向重量级锁的指针 标志位 10 重量级锁定
空,不需要记录信息 标志位 11 GC标记
偏向线程id,偏向时间戳,对象分代年龄 标志位 01 可偏向
(2)对象的类型指针
Type Point对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。并不是所哟肚饿虚拟机实现都必须在对象数据上白哦刘类这阵。如果对象是一个java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通对象的原数据信息确定java对象大小,但是从数组元素的原数据中无法确定数组的大小。
从对象头的Mark Word中可以知道,GC垃圾收集器和锁的信息都是存储在对象头中的,所以可以方便的对对象进行操作。
实例数据对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。
对齐填充并不是必然存在的,仅仅起着占位符的作用,保证对象头部分正好是8字节的倍数。
转载地址:http://nspei.baihongyu.com/