【底层原理之旅—Java对象的内存结构分析】|Java 刷题打卡

简介: 【底层原理之旅—Java对象的内存结构分析】|Java 刷题打卡

题目


Java对象的内存结构分析




知识点


在JVM虚拟机种Java对象的内存结构如图所示分为三大块:对象头(Object Header)、实例数据(Instance Data)、对齐填充(Padding)。 对象头:标记字段、类型指针、数组长度(限于数组对象)


image.png

image.png




  • 对象头(Object header)


  • Mark Word:对象的Mark Word部分占4个字节,其内容是一系列的标记位,比如轻量级的标记位(00),偏向锁标记位(01)等等
  • Class对象指针:Class对象指针的大小也是4个字节,其指向的位置是对象对应的Class对象(其对应的元数据对象)的内存地址。



  • 对象实际数据:这里面包括了对象的所有成员变量,其大小由各个成员变量的大小决定,比如:byte和boolean是1个字节,short和char是2个字节,int和float是4个字节,long和double是8个字节,refrence是4个字节
  • 对齐填充:最后一部分是对齐填充的字节,按8个字节填充




需要注意的点:


对象头(Object Header)

image.png



Mark Word(标记字段)


用于存储对象自身的运行时数据,如哈希码(HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID等。Mark Word被设计成一个非固定的数据结构以便在极小的空间内存储尽量多的信息,它会根据自己的状态复用自己的存储空间

image.png



Klass Pointer(类型指针)

对象指向它的类数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例;


Length(长度)

如果对象是一个Java数组那在对象头中还必须有一块用于记录数组长度的数据


因为虚拟机可以通过普通 Java 对象的元数据信息确定 Java 对象的大小,但是从数组的元数据中无法确定数组的大小

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

image.png



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

image.png



实例数据(Instance Data)


  • 实例数据中存放了对象的字段信息。无论是从父类继承的,还是在子类中定义的,都保存在实例数据中。按照一定顺序存放,在满足这个顺序的条件下,父类定义的字段又会出现在子类定义的变量之前


注意:这部分数据的存储顺序会受到虚拟机分配参数(FieldAllocationStyle)和字段在Java源码中定义顺序的影响

HotSpot虚拟机默认的分配策略如下:

longs/doubles、ints、shorts/chars、bytes/booleans、oop(Ordinary Object Pointers)
复制代码



  • 从分配策略中可以看出,相同宽度的字段总是被分配到一起
  • 在满足这个前提的条件下,父类中定义的变量会出现在子类之前

CompactFields = true;

如果 CompactFields参数值为true(默认为true),那子类之中较窄的变量也可能会插入到父类变量的空隙之中



  • 对齐填充:对齐填充不是必然存在的,没有特别的含义,它仅起到占位符的作用。由于 HotSpot VM 的自动内存管理系统要求对象起始地址必须是 8 字节的整数倍,也就是说对象的大小必须是 8 字节的整数倍。对象头部分是 8 字节的倍数,所以当对象实例数据部分没有对齐时,就需要通过对齐填充来补全


image.png




拓展延伸


实际案例分析


注意:图中的markdown 写错了 应该是 markword ,请见谅!。



在HotspotJVM中,32位机器下,Integer对象的大小是int的几倍

我们都知道在java语言规范已经规定了int的大小是4个字节,那么Integer对象的大小是多少呢?要知道一个对象的大小,那么必须需要知道对象在虚拟机中的结构是怎样的,来看看Hotsopt中对象在内存中的结构:

image.png


在上面这张图里面可以看出,对象在内存中的机构主要包含以下几个部分:


根据上面的图,那么我们可以得出Integer的对象的结构如下:

image.png


Integer只有一个int类型的成员变量value,所以其对象实际数据部分的大小是4个字节,然后再在后面填充4个字节达到8字节的对齐,所以可以得出Integer对象的大小是16个字节。



因此,我们可以得出Integer对象的大小是原生的int类型的4倍



关于对象的内存结构,需要注意数组的内存结构和普通对象的内存结构稍微不同,因为数据有一个长度length字段。所以在对象头后面还多了一个int类型的length字段,占4个字节,接下来才是数组中的数据。如下图:

image.png





















相关文章
|
11月前
|
监控 Java API
现代 Java IO 高性能实践从原理到落地的高效实现路径与实战指南
本文深入解析现代Java高性能IO实践,涵盖异步非阻塞IO、操作系统优化、大文件处理、响应式网络编程与数据库访问,结合Netty、Reactor等技术落地高并发应用,助力构建高效可扩展的IO系统。
331 0
|
11月前
|
存储 缓存 安全
深入讲解 Java 并发编程核心原理与应用案例
本教程全面讲解Java并发编程,涵盖并发基础、线程安全、同步机制、并发工具类、线程池及实际应用案例,助你掌握多线程开发核心技术,提升程序性能与响应能力。
401 0
|
11月前
|
存储 Java 编译器
深入理解Java虚拟机--类文件结构
本内容介绍了Java虚拟机与Class文件的关系及其内部结构。Class文件是一种与语言无关的二进制格式,包含JVM指令集、符号表等信息。无论使用何种语言,只要能生成符合规范的Class文件,即可在JVM上运行。文章详细解析了Class文件的组成,包括魔数、版本号、常量池、访问标志、类索引、字段表、方法表和属性表等,并说明其在Java编译与运行过程中的作用。
337 0
|
11月前
|
人工智能 安全 Java
Go与Java泛型原理简介
本文介绍了Go与Java泛型的实现原理。Go通过单态化为不同类型生成函数副本,提升运行效率;而Java则采用类型擦除,将泛型转为Object类型处理,保持兼容性但牺牲部分类型安全。两种机制各有优劣,适用于不同场景。
622 24
|
12月前
|
存储 缓存 Java
我们来详细讲一讲 Java NIO 底层原理
我是小假 期待与你的下一次相遇 ~
407 2
|
12月前
|
XML JSON Java
Java 反射:从原理到实战的全面解析与应用指南
本文深度解析Java反射机制,从原理到实战应用全覆盖。首先讲解反射的概念与核心原理,包括类加载过程和`Class`对象的作用;接着详细分析反射的核心API用法,如`Class`、`Constructor`、`Method`和`Field`的操作方法;最后通过动态代理和注解驱动配置解析等实战场景,帮助读者掌握反射技术的实际应用。内容翔实,适合希望深入理解Java反射机制的开发者。
985 13
|
算法 Java 索引
说一说 Java 并发队列原理剖析
我是小假 期待与你的下一次相遇 ~
134 1
|
8月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
415 1
|
8月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
388 1