一个Java对象占用多大内存-实践篇

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

在前面的文章《一个Java对象占用多大内存-理论篇》已经了解一个java对象模型组成以及相关理论知识。下面通过一些特定的工具来验证之前的理论说法正确

1. 对象大小查看神器

<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.9</version>
</dependency>
复制代码

jol工具是查看对象大小的神器,能查看对象大小还能查看对象头大小。这里用到的查看对象的大小

1.1 指针压缩开启-对象只包含基础数据类型

对象类:

public class ObjectBase {
​
    //这个对象大小应该是: 8+4+4+8+1+7=32
​
    private int a;
​
    private long b;
​
    private byte c;
​
}
复制代码

测试验证代码:

public class Test1 {
​
    public static void main(String[] args) {
        ClassLayout layout = ClassLayout.parseClass(ObjectBase.class);
        System.out.println(layout.toPrintable());
    }
}
复制代码

测试结果:

image.png 结果和上面的预测一样,有7byte的填充。

1.2 指针压缩开启-对象包含基础数据和引用对象

对象类:

public class ObjectBase {
​
    //这个对象大小应该是: 8+4+4+8+1+4+3=32
​
    private int a;
​
    private long b;
​
    private byte c;
​
    private RefObject refObject;
​
}
public class RefObject {
​
    private int a = 1;
​
    private short b = 2;
​
}
​
复制代码

测试验证代码:

public class Test1 {
​
    public static void main(String[] args) {
        ClassLayout layout = ClassLayout.parseClass(ObjectBase.class);
        System.out.println(layout.toPrintable());
    }
}
复制代码

测试结果:

image.png

1.3 指针压缩开启-数组对象

测试代码:

public class Test1 {
​
    public static void main(String[] args) {
        //ClassLayout layout = ClassLayout.parseClass(ObjectBase.class);
        ClassLayout layout = ClassLayout.parseInstance(new ObjectBase[10]);
        System.out.println(layout.toPrintable());
    }
​
}
复制代码

测试结果:

image.png

1.4 指针压缩关闭

以3.1的代码作为测试代码,增加 -XX:-UseCompressedOops 参数,测试结果为:

image.png

JDK17的情况下竟然没效果。看一下JDK11

image.png

jdk11和预想的一样。

2. 总结

Java对象大小主要由三部分注册:对象头、对象实际数据、填充对齐字段大小三部分组成。而对象头的大小相对固定,在开启了指针压缩的情况下对象头的大小最小12,最大16字节,然后实际数据大小取决于Java对象的成员变量多少。最好就是需要多少的对齐字节。默认的情况下Java对象大小都是8的整数倍。

我是蚂蚁背大象,文章对你有帮助点赞关注我,文章有不正确的地方请您斧正留言评论~谢谢!

参考文档:

猜你喜欢

转载自juejin.im/post/7105200279322099726