如何估算一个对象的大小

2021-06-27  本文已影响0人  农民工进城

如何估算一个对象的大小?
为什么突然会想起这个话题,主要是因为在excel对象等导入导出,或者从数据库中查询出较多的对象时,预估下所占内存的大小,预估风险。

一、Java对象内存布局

要想预估java对象的大小,首先要明确对象内存结构是由哪几部分组成。
一个Java对象主要包括:对象头(Header),实例数据(Instance Data),对齐填充(Padding)。
如下图:


对象内存结构.png

查看是否开启压缩

java -XX:+PrintCommandLineFlags -version
image.png
所以说默认是开启压缩的

当然也可以通过代码,获取一个对象的布局信息。
引入jol 的 maven坐标

  <dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.16</version>
</dependency>

执行以下代码:

    public static void main(String[] args) {
        User user = new User();
        user.setAge(18);
        user.setName("zhaosc");
        System.out.println(ClassLayout.parseInstance(user).toPrintable());
    }
image.png

添加-XX:-UseCompressedOops -XX:-UseCompressedClassPointers参数之后,即去掉压缩,执行。

执行结果如下:


image.png

其中:

既然知道了Java对象内存布局结果,那么如何估算一个对象的大小呢?
对象大小=对象头+实例数+对齐填充
所以关键在于实例数据的计算。

二、实例数据计算

2.1 基本类型的计算

一个Java类的属性值,可能是基本类型或引用类型两种,所以先看简单的基本类型所占内存大小

类型 二进制位数 bytes
boolean 1 1
byte 8 1
char 16 2
short 16 2
Int 32 4
long 64 8
float 32 4
double 64 8
引用类型指针 64或32 在32位系统上每个占用4bytes;在64位系统上每个占用8bytes,开启指针压缩后占用4个
2.2引用类型的计算

引用类型的计算相对于基本类型的计算来说,比较麻烦。
大致思路是:将引用类型,转换为基本类型,一个引用指针占用4个字节,对象头占用12个字节(因为默认开启压缩),如果数组,再加上4个字节的数组长度,不是8的倍数,对齐补充

public class User {
    private String name;
    private int age;
}

还是以

User user = new User();
user.setAge(18);
user.setName("zhaosc");

User类型:头部(8+4)+int(4)+String的引用类型(4)+padding(4)=24字节
String类型:头部(8+4)+int(4)+指向char[]对象的引用类型(4)+padding(4)=24字节
char[]类型:头部(8+4)+数组长度(4)+“zhaosc”(26)+padding(4)=32字节
所以一共是24+24+32=80字节,80
8=640bit

上一篇 下一篇

猜你喜欢

热点阅读