Java对象头结构

本文详细介绍了Java对象的内存结构,包括对象头的MarkWord、ClassPointer和可选的ArrayLength字段,对象体的实例变量,以及对齐字节的作用。对象头的MarkWord用于线程锁状态和哈希码存储,ClassPointer指向类对象信息,ArrayLength记录数组长度。此外,还讨论了64位JVM中对象指针压缩选项UseCompressedOops及其影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java对象(Object 实例) 结构包含三部分:对象头、对象体、对其子节,具体如下图所示

 

对象的三个部分 

对象头

        对象头包括三个字段,第一个字段叫作Mark Word (标记字),用于存储自身运行时的数据,例如GC标志位、哈希码、锁状态等信息。
        第二个字段叫作Class Pointer (类对象指针),用于存放方法区Class对象的地址,虚拟机通过这个指针来确定这个对象是哪个类的实例。

        第三个字段叫作Array Length (数组长度)。如果对象是-个Java数组,那么此字段必须有,用于记录数组长度的数据;如果对象不是一一个Java数组, 那么此字段不存在,所以这是一个可选字段。


对象体

        对象体包含对象的实例变量(成员变量),用于成员属性值,包括父类的成员属性值。这部分内存按4字节对齐。

对齐字节

        对齐字节也叫作填充对齐,其作用是用来保证Java对象所占内存字节数为8的倍数HotSpot VM的内存管理要求对象起始地址必须是8字节的整数倍。对象头本身是8的倍数,当对象的实例变量数据不是8的倍数时,便需要填充数据来保证8字节的对齐。

对象结构中核心字段的作用


Mark Word (标记字)

        字段主要用来表示对象的线程锁状态,另外还可以用来配合GC存放该对象的hashCode。后续单独在并发专题讲解该部分内容。

Class Pointer (类对象指针)

是一一个指向方法区中Class信息的指针,意味着该对象可随时知道自己是哪个Class的实例。


Array Length (数组长度)

        字段占用32位(在32位JVM中) 字节,这是可选的,只有当本对象是一个数组对象时才会有这个部分。


对象体

用于保存对象属性值,是对象的主体部分,占用的内存空间大小取决于对象的属性数量和类型。比如实体类中的变量。


对齐字节

并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。当对象实例数据部分没有对齐(8字节的整数倍)时,就需要通过对齐填充来补全。


对象结构中的字段长度


        Mark Word、Class Pointer、Array Length等字段的长度都与JVM的位数有关。Mark Word的长度为JVM的一个Word (字)大小,也就是说32位JVM的Mark Word为32位,64位JVM的Mark Word为64位。Class Pointer (类对象指针)字段的长度也为JVM的一个Word (字)大小,即32位JVM
Mark Word为32位,64位JVM的Mark Word为64位。
        对于对象指针而言,如果JVM中的对象数量过多,使用64位的指针将浪费大量内存,通过简
单统计,64位JVM将会比32位JVM多耗费50%的内存。为了节约内存可以使用选项
+UseCompressedOops开启指针压缩。UseCompressedOops 中的Oop为Ordinary object pointer (普通对象指针)的缩写。
如果开启UseCompressedOops选项,以下类型的指针将从64位压缩至32位:

  • Class对象的属性指针(静态变量)。
  • Object对象的属性指针(成员变量)。
  • 普通对象数组的元素指针

当然,也不是所有的指针都会压缩,一些特殊类 型的指针不会压缩,比如指向PermGen (永久代)的Class对象指针(JDK 8中指向元空间的Class对象指针)、本地变量、堆栈元素、入参、返回值和NULL指针等。


说明
        

        在堆内存小于32GB的情况下,64位虚拟机的UseCompressedOops选项是默认开启的,该选项表示开启Oop对象的指针压缩会将原来64位的Oop对象指针压缩为32位。


手动开启Oop对象指针压缩的Java指令为:

java -XX: +UseCompressed0ops mainclass


手动关闭Oop对象指针压缩的Java指令为;
 

java -XX:-UseCompressedoops mainclass

        如果对象是一个数组,那么对象头还需要有额外的空间用于存储数组的长度(Array Length字段)。Array Length字段的长度也随着JVM架构的不同而不同:在32位JVM上,长度为32位;在64位JVM.上,长度为64位。64位JVM如果开启了Oop对象的指针压缩,Array Length字段的长度也将由64位压缩至32位。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值