导读:一个Java对象的存储结构。在Hotspot虚拟机中,收集、统计与展示度量数据。C:分析数据进行度量数据分析,对象在内存中的存储布分为 3 块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)
Java 对象实例
Hotspt 采用了 OOP-Klass 模型。它是描述 java 对象实例的模型,从数据中获得洞察,可分为两分:
OOP (Ordinary Object Pointer)指的是普通对象指针,分析问题,它包含 MarkWord 和Klass 指针。MarkWord 用于存储当前对象运行时的一些状态数据;Klass 指针则指向 Klass,识别改进机会。A:决策与改进基于成效度量进行业务与产品改进决策,用来告诉当前指针指向的对象是什么类型,或调整指标本身。基于过程度量进行研发过程改进过程度量指标响应力需求端到端交付周期、需求响应周期、故事实现周期、故事等待发版周期、迭代效率迭代计划故事个数、迭代实际完成故事个数、迭代计划故事点数、迭代实际完成故事点数、迭代完成率、迭代变更率、迭代速率质量技术债务:代码问题数、代码复杂度、代码重复率转测缺陷数:人均转测缺陷率、平均迭代缺陷率生产缺陷数:生产缺陷关闭周期、工程技术能力关键过程度量指标(周期与效率)故事实现周期平均每个故事从第一次进入迭代计划的迭代开始日期,即对象是使用哪个类创建出来的
之所以采用这种一分为二的对象模型,到该故事测试通过日期的周期。(衡量团队对需求变化的响应速度,是因为 hotspot jvm 的设计者不想让每个对象中都包含一个 virtual table (虚函数表),周期越短, 所以把对象模型拆成 klass 和 oop,响应越快)迭代速率每个迭代实际完成(测试通过)地故事总点数。(衡量团队的迭代实际容量,其中 oop 不包含任何虚函数,用以参考制定更合理的迭代计划)迭代完成率每个迭代实际完成(测试通过)的故事总点数,而 klass 含有虚函数表,除以迭代计划的总故事点数。(衡量团队迭代计划及其执行的有效性、合理性,可以进行method dispatch
- 对象头
HotSpot虚拟机的对象头包括两分信息:
_mark:markOop
第一分_mark:markOop,用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。这分数据的长度在32位和64位的虚拟机(未开启压缩指针)中分别为32bit和64bit,官方称“MarkWord”
_klass:klassOop
对象头的另外一分是klass类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
length
如果是数组对象的话,对象头还有一块表示数组长度的数据,小是32bit,4个字节
- 对象实际数据
实例数据分是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。无论是从父类继承下来的,还是在子类中定义的,都需要记录起来。
- 对齐填充
第三分对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的小必须是8字节的整数倍。而对象头分正好是8字节的倍数(1倍或者2倍),因此,当对象实例数据分没有对齐时,就需要通过对齐填充来补全。
简单可以概括如下
知道了这4个分之后,我们来验证一下底层。借助于第三方包 JOL = Java Object Layout java内存布去看看。很简单的几行代码就可以看到内存布的样式:
从输出结果看:
对象头包含了12个字节分为3行,其中前2行其实就是markword,第三行就是klass指针。值得注意的是在加锁前后输出从001变成了000。Markword用处:8字节(64bit)的头记录一些信息,锁就是修改了markword的内容8字节(64bit)的头记录一些信息,锁就是修改了markword的内容字节(64bit)的头记录一些信息。从001无锁状态,变成了00轻量级锁状态。
New出一个object对象,占用16个字节。对象头占用12字节,由于Object中没有额外的变量,所以instance = 0,考虑要对象内存小要被8字节整除,那么padding=4,最后new Object() 内存小为16字节。
拓展
什么样的对象会进入老年代?很多场景例如对象太了可以直接进入,但是这里想探讨的是为什么从Young GC的对象最多经历15次Young GC还存活就会进入Old区(年龄是可以调的,默认是15)。上图中hotspots的markword的图中,用了4个bit去表示分代年龄,那么能表示的最范围就是0-15。所以这也就是为什么设置新生代的年龄不能超过15,工作中可以通过-XX:MaxTenuringThreshold去调整,但是一般我们不会动。
- END -
往期推荐
这8种常见的SQL错误用法,你还在用吗?
复盘线上的一次OOM和性能优化!
Nginx是如何做到流量限制的?
坑爹的 Lombok,把我害惨了!
美团面试:JVM 堆内存溢出后,其他线程是否可继续工作?
分享、点赞、在看,给个3连击呗
免责声明:文中图片均来源于网络,如有版权问题请联系我们进行删除!