Java对象内存结构、对象在内存是什么样的

我们知道Java对象分配在堆内存中,一个对象在堆内存中的存储布局可以分为三部分:

  • 对象头Header
  • 实例数据
  • 对齐填充

1. 对象头Header

对象头部分又包含两部分:

  • 第一部分是用于存储对象自身运行时数据,例如哈希码、GC分代年龄等
  • 第二部分就是类型指针,即此对象是哪一个类的实例。

如果是Java数组对象,那么除了这两部分外,还会有一部分用来记录数组的长度。

先说运行时数据,这个是最重要的

1.1 运行时数据

Java对象的对象头中,这部分存储Java对象运行时的数据,这些数据可以是哈希码、GC分代年龄、锁标志状态等等,这部分数据被官方称为“Mark Word"。
这部分数据的长度在32位和64位的虚拟机中分别是32bit和64bit。
由于对象要存储的运行时数据很多,超过了32bit、64bit,为了提高利用效率,“Mark Word"中的内容是动态改变的。
以32bit的虚拟机为例:
“Mark Word"占用32位,有两位用来作为标记位,标记对象的锁状态,在不同的锁状态下,”Mark Word"真正存储的数据是不一样的。

锁标志位锁状态真正存储的内容
01未锁定(可不偏向)对象的哈希码、分代年龄
00轻量级锁定指向锁记录的指针
10重量级锁定(膨胀)指向重量级锁的指针
11GC标记空,不需要记录信息
01可偏向偏向线程ID、偏向时间戳、对象分代年龄等

1.2 类型指针

指向此对象类型元数据的指针,JVM就是通过这个指针来判断这个对象是哪一个类的实例。

2. 实例数据

就是对象真正存储的数据信息,例如一些字段、属性的值等。

3. 对齐填充

举个例子,语文作文要求至少400字,那么我为了凑够这400字,在作文末尾连续写了很多个标点符号。
那么在对象中,这一部分的作用也是这样的,这一部分不是必然存在的,没有特别的含义,就是为了凑够对象所占用的字节数。
HotSpot虚拟机的自动内存管理要求对象的起始地址必须是8字节的整数倍,换句话说,就是任何Java对象的大小都必须是8字节的整数倍,那么对齐填充这一部分就是为了使对象能够达到8字节整数倍的大小,当对象除了对齐填充外的其他部分的大小已经满足8字节的整数倍了,那么就不需要对齐填充了。

posted @   秋天Code  阅读(36)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示