java中的对象在内存里是什么(对象在内存中的存储)
导语:Java面试必考问题:对象在内存中是如何布局的?
HotSpot对象的内存布局
对象的内存布局在HotSpot虚拟机中,对象在内存中的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对象填充(Padding)。
HotSpot JVM对象在内存中的布局
实例数据: 包括了对象的所有成员变量,大小由各变量的类型决定,包括基本类型和引用类型,这是对象真正存储的有效信息;
对齐填充: 由于虚拟机要求对象起始地址必须是8字节的整数倍,填充数据的存在主要是为了字节对齐。
对象头: HotSpot虚拟机的对象头主要包括两部分数据:标记字段(Mark Word)、类型指针(Class Pointer)。如果是数组的话,还包括数组长度,不是数组就没这部分。
未开启指针压缩和开启指针压缩的对象头,默认都是开启的
类型指针指向方法区中类的元数据
虚拟机通过对象头的这个类型指针(也称为Klass Word)来确定这个对象是哪个类的实例。下面我们重点介绍一下对象头的Mark word。
Mark word
Mark Word 用于存储对象自身的运行时数据,Java对象头以一字宽的长度存储Mark Word,里面包含了对象的hashCode,分代年龄和锁标记位。
在32位虚拟机中,1字宽等于4字节,即32bit;在64位虚拟机下,1字宽等于64bit。
运行期间,Mark Word的数据类型会随着锁标志位的改变而改变,一共有以下几种状态:无锁态、偏向锁、轻量级锁、重量级锁和可回收(GC标志)。
32位Mark word的几种锁状态
回顾前文介绍过 synchronized 关键字为临界区代码加的是对象锁,也就是重量级锁,是通过监视器对象(ObjectMonitor)来实现线程互斥的,有时也被翻译为管程,其底层是依赖于操作系统的互斥量。当对象的锁状态为重量级锁时,Mark Word中的指针就指向了Monitor的地址。
由于互斥锁的线程切换系统开销太大,所以后来Java虚拟机又引入了开销更小的偏向锁和轻量级锁,适用于线程竞争不激烈的场合使用。JVM可以通过参数 -XX:-UseBiasedLocking 选择开启或不开启偏向锁。
如果不开启偏向锁,那么刚创建的对象的锁状态就是无锁态,即锁标志位是01,Mark word中存储的是对象hashcode;如果开启偏向锁,那么刚创建的对象的锁状态是偏向锁状态,线程Id为0,表示尚未有线程获取,不偏向任何线程;偏向锁被线程获取以后,Mark word就存储线程Id。
开启偏向锁的JVM,随着线程竞争的升级,会将偏向锁升级为轻量级锁,再进一步膨胀为重量级锁。对象的Mark word中的数据和锁标志位也会随之改变。
当一个对象被标记了GC标志,那么这个对象即将被垃圾回收,Mark Word中的数据自然是空的了。
我会持续更新关于物联网、云原生以及数字科技方面的文章,用简单的语言描述复杂的技术,也会偶尔发表一下对IT产业的看法,欢迎大家关注,谢谢。
本文内容由小媛整理编辑!