一个对象通常由头和内容组成。想要计算一个对象的大小,我们就需要分别计算头部的大小和内容的大小。

查看一个对象的大小

首先在pom文件中引入apache下面的lucene-core依赖,然后调用对应的shallowSizeOf()方法。

<dependency>
    <groupId>org.apache.lucene</groupId>
    <artifactId>lucene-core</artifactId>
    <version>6.6.1</version>
</dependency>
public class Test {
    public static void main(String[] args) {
        Integer integer = new Integer(10);
        System.out.println(RamUsageEstimator.shallowSizeOf(integer));  //结果为16
    }
}

可以看到Integer对象的大小是16个字节。

头部大小

对象的头通常会存储该对象地址标记(里面存储有该对象的锁,hashcode,年龄等信息)等信息。其中,地址会占用4个字节,标记会占用8个字节。也就是说,一个对象的头部默认会占用4+8=12个字节。另外,如果该对象是一个数组的话,头部还需要额外的4个字节来存储该数组的长度(因为JVM使用一个int类型的变量来记录数组的长度,而int类型长度为4个字节)。也就是说,对于一个数组对象的话,它的头部会占用4+8+4=16个字节。

内容大小

为了计算内容大小,我们需要查看该对象的类内部的方法和变量。以上面的Integer对象为例,进入其代码中我们可以看到大部分的变量都是用static来修饰的,这样的变量会被存在方法区,并不算做Java对象的大小。除此之外,类的方法也是存储在方法区的,也不会被计算。

java 对象最小有多大 java对象大小sizeof_java


而该Integer对象的值是用int变量来存储的,并没有用static修饰,这意味着value变量将占用4个字节。

java 对象最小有多大 java对象大小sizeof_开发语言_02


因此,一个Integer对象的大小就是4+8+4=16个字节,这也和上面程序输出的大小一致。

注意点

需要注意的是,由于Java的存储是以8字节为单位扩展的,所以Java的对象的大小都是8字节的整数倍。如果头部+内容的大小不是8的倍数,将自动补充为8字节的整数倍。如Hashmap占用48个字节,但是实际上看代码Hashmap只占用了44个字节,这就是因为44字节自动填充为了48字节。