对象内存布局详解
2022-01-05 18:09:43 5 举报
对象内存布局详解
作者其他创作
大纲/内容
8
实例数据部分是对象真正存储的有效信息,也是程序代码中所定义的各种类型的字段内容。无论是从父类继承下来的,还是子类中定义的,都需要记录起来。
类型指针
数组长度
运行时数据(Mark world)
压缩指针超过32G内存失效问题
对象内存布局(对象存储)
如果对象是一个 Java 数组,那在对象头中还必须有一块用于记录数组长度的数据。因为虚拟机可以通过普通 Java 对象的元数据信息确定 Java 对象的大小,但是从数组的元数据中无法确定数组的大小。数组长度就是4个字节
实例数据
0
类型指针4个字节堆2的32次幂
5
1
2
对其填充
对象头
由于Java面向对象的思想,在JVM中需要大量存储对象,存储时为了实现一些额外的功能,需要在对象中添加一些标记字段用于增强对象功能,这些标记字段组成了对象头。在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header),实例数据(Instance Data)和对齐填充(Padding)。也就是说 JAVA对象 = 对象头 + 实例数据 + 对象填充。其中,对象头由两部分组成,一部分用于存储自身的运行时数据,称之为 Mark Word,另外一部分是类型指针,及对象指向它的类元数据的指针。对象头 = Mark Word + 类型指针(未开启指针压缩的情况下)在32位系统中,Mark Word = 4 bytes = 32 bits,对象头 = 8 bytes = 64 bits;在64位系统中,Mark Word = 8 bytes = 64 bits ,对象头 = 16 bytes = 128bits;
对齐填充不是必然存在的,仅起到占位符的作用。64位虚拟机中,因为HotSpot虚拟机规定自动内存管理系统要求对象其实地址必须是8字节的整数倍,换句话说,就是对象的大小是8字节的整数倍,如果不满足条件,则需要对齐填充来补全。
第一部分用于存储对象自身的运行时数据,比如哈希码、GC分代年龄(用于垃圾回收)、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。这部分数据的长度取决于虚拟机的位数,在32位和64位虚拟机中长度分别为32bit和64bit。
6
2的三次幂×2的32次幂
-XX:+PrintCommandLineFlags 激活输出命令-XX:InitialHeapSize 最小堆内存-XX:MaxHeapSize 最大堆内存 最小堆内存和最大堆内存最好设置成一直否则会造成堆的弹性伸缩。-XX:+UseCompressedClassPointers 使用类指针压缩-XX:+UseCompressedOops 使用普通对象指针压缩类指针在 未开启-XX:+UseCompressedClassPointers参数时 是8个字节 开启之后是4个字节 默认开启普通对象指针 String 在未开启-XX:+UseCompressedOops参数之前是8个字节,开启之后是4个字节。-XX:-UseCompressedOops 关闭该参数 类型指针压缩功能也会失效压缩指针堆内存超过32G失效JVM的实现方式是不再保存所有引用,而是每隔8个字节保存一个引用。例如,原来保存每个引用0、1、2…,现在只保存0、8、16…。因此,指针压缩后,并不是所有引用都保存在堆中,而是以8个字节为间隔保存引用。在实现上,堆中的引用其实还是按照0x0、0x1、0x2…进行存储。只不过当引用被存入64位的寄存器时,JVM将其左移3位(相当于末尾添加3个0),例如0x0、0x1、0x2…分别被转换为0x0、0x8、0x10。而当从寄存器读出时,JVM又可以右移3位,丢弃末尾的0。(oop在堆中是32位,在寄存器中是35位,2的35次方=32G。也就是说,使用32位,来达到35位oop所能引用的堆内存空间)
7
3
4
虚拟机:Java HotSpot™ 64-Bit Server VM对象的内存以字节为单位,必须是8的倍数,它的构成由3部分组成:对象头+实例数据+对齐内存。对象头主要包括对象的运行行元数据,比较哈希码、GC分代年龄、锁状态标志还有类型指针,类型指针指向类元数据,表明该对象所属类型。实例数据包括自身数据和所有父级数据,所有父级占内存大小都是8的倍数,没有就需要补齐。类型指针一般为4字节,在关闭压缩普通对象指针时(-XX:+UseCompressedOops)为8字节,UseCompressedOops默认是开启的,只有虚拟机内存达到32G以上,4个字节已经无法满足寻址需求时,才需要关闭该参数。普通对象头除类型指针外的大小为8字节,在开启压缩总大小为12字节,不开启压缩总大小为16字节;数组对象头在开启压缩时是16字节,不开启压缩为24字节。各种类型大小如下:对象类型 字节boolean 1byte 1short 2char 2int 4float 4long 8double 8引用类型 开启指针压缩为4,不开启为8普通对象头 开启指针压缩为12,不开启为16数组对象头 开启指针压缩为16,不开启为24
第二部分用于存储类型指针,也就是对象指向它的类元数据的指针。虚拟机通过这个指针确定对象是哪个类的实例。开启压缩指针4字节,否则8字节。
0 条评论
下一页
为你推荐
查看更多