Integer到底占用多大的空间

2021.03.04 08:03 455
阅读约 2 分钟

在Java开发中我们经常会接触到Integer这个包装类,我们经常说Integer占用4个字节,32比特,其数据的表示范围是-2^31 ~ 2^31-1之间,但是作为一个实例对象存在时,真实情况只是这样吗?

这里我们需要用到一个工具,JProfile

一个空对象的大小

这里请尝试运行下面的代码

public class TestInteger {
    public static void main(String[] args) {
        TestObject testObject = new TestObject();

        Scanner scanner = new Scanner(System.in);
        scanner.next();
    }
}

class TestObject {
}

此处我们创建了一个空对象,现在我们打开工具看一下一个空对象所占用的内存

可以看到内存占用为16bytes,这里我们需要了解一些概念,也就是一个java对象的组成结构,请看下面这张图:

一个非数组实例由三部分组成,对象头,对象实际数据以及可能存在的对齐填充。

对象头

HotSpot虚拟机的对象头包含两部分信息:

  • 第一部分markword中储存了该实例的哈希码、GC分代年龄、等待队列、EntrySet、偏向线程ID、偏向时间戳、对象状态,这部分数据的长度在32位和64位的虚拟机(未开启压缩指针)中分别为32bit和64bit,官方称它为“MarkWord”。
  • 对象头的另一部分是kclass,类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例.

实例数据

真正储存数据的部分

对齐填充

HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,也就是说,不足8字节倍数部分需要补上。

了解完这些知识后,我们再来解释一下为什么一个空对象占用的字节数为16字节。

Java8中的hotspot虚拟机默认开启了指针压缩,因此一个空对象的实际大小为 

12字节的对象头 + 4字节的对齐 = 16字节

这也验证了我们之前工具所获得的结论。

//禁用指针压缩的jvm指令
-XX:-UseCompressedOops

一个Integer对象的大小

现在,让我们测试一下一个Integer对象的大小,代码很简单

class TestObject {
    private Integer i = 128;
}

这次得到的测试结果如下图所示,这里还有一个概念,关于RetainedSize 与 Shallow Size

因为我们的对象头已经占用了16字节的空间,那么显然Integer也占用了16字节的大小,计算方式如下

12字节的对象头 + 4字节的实际储存空间 = 16 字节

其它类型的大小各位看官有兴趣的话可以自行尝试一下。

 

字数:303 发布于 7 个月前
Copyright 2018-2021 Siques