一文搞定Java对象以及数组在堆区中所占空间大小(图解)

JVM运行时数据区(Runtime Data Area)分为JVM栈(Java栈)、堆区(Heap)、方法区、本地方法栈和程序计数器,而Java中的对象和数组(数组可以理解为特殊的对象)是存放在堆区的,这篇文章详细解析对象以及数组在堆区中所占空间大小。

对象在堆区中所占空间大小

结构示意图

先来看一下对象在堆区存储的结构示意图

对象头(Object Head)

标记字和类型指针统称对象头

标记字(Mark Word)

标记字在32位机器占用4字节,在64位机器占用8字节,主要用来表示对象的线程锁状态,还可以用来配合GC、存放该对象的 HashCode。

类型指针(Klass Pointer)

类型指针即当前对象所属类型的指针,封装了语言级别的类信息,例如类名、其修饰符、超类信息等。

加载类的时候类的加载器会将.class字节码文件加载到内存中,即创建一个该类的Class实例,用来表示这个类的元数据,包括常量池、字段、方法等,存放在方法区。

而类型指针(Klass Pointer)就是指向方法区中的Class实例。

类型指针所占的空间大小跟JVM的一个参数“类型指针压缩”(UseCompressedClassPointers)有关,

类型指针压缩参数在开启时类型指针是占4个字节,关闭时类型指针是占8个字节。请注意,该参数是默认开启的,也就是说类型指针默认被压缩为4个字节。(在64位机器上)

在32位机器上,类型指针占用一个字,即4个字节。

实例数据(Instance Data) / 对象体(Object Body)

该部分存储本对象的实例数据(即未被static修饰的变量),实例数据又分为基本数据类型和引用类型。

而静态变量(即被static修饰的变量)不存储在实例对象中,存放在方法区中的Class实例的尾部,被该类的所有对象所共享。

基本数据类型

基本数据类型及所占字节数:

boolean:1字节

char:2字节

byte:1字节

short:2字节

int:4字节

long:8字节

float:4字节

double:8字节

引用数据类型

HotSpot JVM 使用称为普通对象指针 (OOPS, Ordinary Object Pointers) 的数据结构来表示对象指针(即引用数据类型)。它的大小与JVM的另外一个参数“普通对象指针压缩”(UseCompressedOops)有关。

在普通对象指针压缩参数开启时引用占4个字节,关闭时引用占8个字节。

对齐(Padding) / 填充物

由于JVM规定每个对象占用的总空间是8的倍数,故对象占用的总空间(对象头+对象体)不是8的倍数时,会自动补齐字节,使整个对象加上对齐所占用的空间为8的倍数。

例子

public class Test {
    int i;
    long l;
    Long L;
}

在默认开启两个压缩参数时,该类的一个对象在堆占的内存为8(标记字)+4(被压缩的类型指针)+4(int)+8(long)+4(被压缩的包装类引用Long)+4(将前面的28字节对齐,补为8的倍数32字节)

数组在堆区中所占空间大小

结构示意图

先来看一下数组在堆区存储的结构示意图 

数组与对象唯一的区别是只比对象多了一个占4字节的数组长度(Length),其他均与对象相同。

例子 

默认开启两个压缩参数时,

new Double[10] = 8(Mark Word) + 4(压缩后的Klass Pointer) + 4(Length,4字节长的数组长度记录数组的长度) + 10 * 4(Instance Data,10个被压缩后的包装类引用Double,每个占4字节) + 0(长度为568的倍数,不用对齐) = 56 Bytes

new char[7] = 8(Mark Word) + 4(压缩后的Klass Pointer) + 4(Length,4字节长的数组长度记录数组的长度) + 7 * 2(Instance Data,7个基本数据类型char,每个占2字节) + 2(将前面的30字节补位8的倍数32字节) = 32 Bytes

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一陸向北

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值