概述

一个对象本身的内在结构需要一种描述方式,这个描述信息是以字节码的方法存储在方法区中的。
Class 本身就是一个对象,都以 KB 为单位,如果 new Integer() 为了表示一个数据就占用KB级别的内存就有点不值了,下面讲解 JVM 是如何做的。
为了表示对象的属性、方法等信息,不得不需要结构描述。Hotspot VM 使用对象头部的一个指针指向 Class 区域的方式来找到对象的 Class 描述,以及内部的方法、属性入口。如下图所示:

在 HotSpot 虚拟机中,对象在内存中存储布局分为 3 块区域:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding),下面详细讲解各部分内容。

对象头(Header)

HotSpot 虚拟机的对象头包括两部分(非数组对象)信息,如下图所示:

  • 第一部分用于存储对象自身的运行时数据,如哈希码(HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳、对象分代年龄,这部分信息称为“Mark Word”;Mark Word 被设计成一个非固定的数据结构以便在极小的空间内存储尽量多的信息,它会根据自己的状态复用自己的存储空间。
  • 第二部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例;
  • 如果对象是一个 Java 数组,那在对象头中还必须有一块用于记录数组长度的数据。因为虚拟机可以通过普通 Java 对象的元数据信息确定 Java 对象的大小,但是从数组的元数据中无法确定数组的大小。

这部分数据的长度在 32 位和 64 位的虚拟机(未开启压缩指针)中分别为 32bit 和 64bit。

例如,在 32 位的 HotSpot 虚拟机中,如果对象处于未被锁定的状态下,那么 Mark Word 的 32bit 空间中的 25bit 用于存储对象哈希码,4bit 用于存储对象分代年龄,2bit 用于存储锁标志位,1bit 固定为 0,如下表所示:

在 32 位系统下,存放 Class 指针的空间大小是 4 字节,Mark Word 空间大小也是4字节,因此头部就是 8 字节,如果是数组就需要再加 4 字节表示数组的长度,如下表所示:

在 64 位系统及 64 位 JVM 下,开启指针压缩,那么头部存放 Class 指针的空间大小还是4字节,而 Mark Word 区域会变大,变成 8 字节,也就是头部最少为 12 字节,如下表所示:

压缩指针:开启指针压缩使用算法开销带来内存节约,Java 对象都是以 8 字节对齐的,也就是以 8 字节为内存访问的基本单元,那么在地理处理上,就有 3 个位是空闲的,这 3 个位可以用来虚拟,利用 32 位的地址指针原本最多只能寻址 4GB,但是加上 3 个位的 8 种内部运算,就可以变化出 32GB 的寻址。

实例数据(Instance Data)

实例数据部分是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。

这部分的存储顺序会受到虚拟机分配策略参数(FieldsAllocationStyle)和字段在 Java 源码中定义顺序的影响。

对齐填充(Padding)

对齐填充不是必然存在的,没有特别的含义,它仅起到占位符的作用。

由于 HotSpot VM 的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍,也就是说对象的大小必须是 8 字节的整数倍。对象头部分是 8 字节的倍数,所以当对象实例数据部分没有对齐时,就需要通过对齐填充来补全。

估算对象大小

32 位系统下,当使用 new Object() 时,JVM 将会分配 8(Mark Word+类型指针) 字节的空间,128 个 Object 对象将占用 1KB 的空间。
如果是 new Integer(),那么对象里还有一个 int 值,其占用 4 字节,这个对象也就是 8+4=12 字节,对齐后,该对象就是 16 字节。

以上只是一些简单的对象,那么对象的内部属性是怎么排布的?

Class A {int i;byte b;String str;
}

其中对象头部占用 ‘Mark Word’4 + ‘类型指针’4 = 8 字节;byte 8 位长,占用 1 字节;int 32 位长,占用 4 字节;String 只有引用,占用 4 字节;
那么对象 A 一共占用了 8+1+4+4=17 字节,按照 8 字节对齐原则,对象大小也就是 24 字节。

这个计算看起来是没有问题的,对象的大小也确实是 24 字节,但是对齐(padding)的位置并不对:

在 HotSpot VM 中,对象排布时,间隙是在 4 字节基础上的(在 32 位和 64 位压缩模式下),上述例子中,int 后面的 byte,空隙只剩下 3 字节,接下来的 String 对象引用需要 4 字节来存放,因此 byte 和对象引用之间就会有 3 字节对齐,对象引用排布后,最后会有 4 字节对齐,因此结果上依然是 7 字节对齐。此时对象的结构示意图,如下图所示:

参考资料

[1] Java特种兵, 3.5 - 浅析Java对象的内存结构

[2] Java并发编程的艺术, 2.2.1 - Java对象头

[3] 深入理解Java虚拟机, 2.3.2 - 对象的内存布局

转载于:https://www.cnblogs.com/zhengbin/p/6490953.html

JVM——深入分析对象的内存布局相关推荐

  1. 欧尼酱讲JVM(18)——对象实例化内存布局与访问定位

    目录 对象的实例化 创建对象的几种方式 从字节码角度看对象的创建过程 对象创建的六个步骤 第一步:判断对象对应的类是否加载.链接.初始化 第二步:为这个对象分配内存 第三步:处理并发安全问题 第四步: ...

  2. 详解JVM内存管理与垃圾回收机制3 - JVM中对象的内存布局

    在Java语言层面,可以通过Class类来描述普通的Java类,当JVM创建对象的同时,会生成对应的Class对象,用来描述此对象的大致模型,这也是反射的基础.那么在JVM的内部是如何描述一个普通的对 ...

  3. JVM从入门到精通(四):内存屏障与JVM指令,对象的内存布局

    JMM 硬件层数据一致性 协议很多,intel 用MESI https://www.cnblogs.com/z00377750/p/9180644.html 现代CPU的数据一致性实现 = 缓存锁(M ...

  4. JVM 的内存模型及对象的内存布局(一图尽收眼底)

    JVM 的内存模型 Java 数据类型对象的内存布局 2.1 Example layout of a java.lang.Integer object for a 32-bit Java proces ...

  5. jvm学习笔记(2)——java对象的内存布局

    一.内存布局: 一个java对象在内存中可分为3个区域:对象头(Header).实例数据(Instance Data).对齐填充(Padding). 对象头(两部分): 对象自身运行时的数据.如哈希码 ...

  6. 动态加载laydate 失效_Java对象的内存布局+反射的原理+动态代理+ 并发和锁+文末彩蛋...

    # 一行代码是怎么运行的 首先,java代码会被编译成字节码,字节码就是java虚拟机定义的一种编码格式,需要java虚拟机才能够解析,java虚拟机需要将字节码转换成机器码才能在cpu上执行. 我们 ...

  7. 对象实例化指针_JVM第三课:一文讲透对象的内存布局和访问方式

    对象的内存布局和访问定位 对象的实例化 对象的创建方式 new Class的newInstance方法 Class> aClass = Class.forName("com.mu.Co ...

  8. Java对象创建的过程及对象的内存布局与访问定位

    这里以HotSpot为例,且所说的对象指普通的Java对象,不包括数组和Class对象等. 1.对象创建的过程 1.类加载.解析.初始化:虚拟机遇到new时先检查此指令的参数是否能在常量池中找到类的符 ...

  9. java怎么限制一个对象的内存_java对象的内存布局及创建过程

    一.对象的内存布局 对象的内存结构又可以被分为:对象头,实例数据,对象填充 对象头:对象头结构在32位JVM与64位JVM中的实现细节是不同的 32bit: 64bit: 实例数据:对象真正存储的有效 ...

最新文章

  1. mysql执行ref_ref:mysql命令大全
  2. 派生类中构造函数与虚构函数的研究
  3. 【Python】Python入门:4000字能把元组tuple讲透吗?
  4. java ==和===_java中==和equals的区别详解
  5. android shape 圆角百分比,Android shape显示圆角问题
  6. WritePrivateProfileString等读写.ini配置文件
  7. Spring Cloud实战小贴士:turbine如何聚合设置了context-path的hystrix数据
  8. SpringBoot--springboot启动类和controller的配置
  9. ft232h引脚_一种基于芯片ft232h的usb接口电路的制作方法
  10. 016、JVM实战总结:大厂面试题:JVM中有哪些垃圾回收算法,每个算法各自的优劣?
  11. K - Repeating Decimals(循环小数)
  12. OpenCV Show Image cvShowImage() 使用方法
  13. 江苏2021168查询高考成绩,重磅!高考成绩查询!!
  14. 抽奖滚动文字如何透明地覆盖在动态视频背景上?-活动现场双屏管理系统操作提示
  15. 软考信息系统项目管理师知识点总结2
  16. ebm风扇选型手册_德国EBM全系列散热风扇
  17. 数学建模入门-python实现单目标模糊综合评价法
  18. CSS中button标签自带border属性
  19. 记一次线上微信公众号迁移遇到的坑
  20. 腾讯云主机SSH连接不上如何解决

热门文章

  1. 怎么讲d 盘里的软件弄到桌面_GNOME 2 粉丝喜欢 Mate Linux 桌面的什么?
  2. 设计模式--装饰器模式
  3. 目标追踪-背景差算法
  4. 不同工作组能访问吗_「长笛众测」你能听出3K-9W不同价位长笛的区别吗?
  5. python cmdb_Django之入门 CMDB系统 (一) 基础环境
  6. 【clickhouse】clickhouse 表引擎之 null
  7. 【MySQL】MySQL监控工具 mysql-monitor
  8. 95-110-026-源码-Env-RemoteStreamEnvironment
  9. 95-130-346-源码-source-kafka相关-KafkaConsumerThread
  10. 【CDH】 kafkaServer-gc.log日志太多