你的java对象占了多大的内存?

刚开始学习java的时候,知道了继承的概念,子类会继承父类的属性,private和default(不在一个包时)的除外。当时不明白父类和子类是怎么保存属性的值,但是了解了JOL,终于有机会解开这个长时间困扰心头的问题。

首先,网上有一种说法,当你创建一个子类对象的时候会同时创建一个父类对象,并且子类对象会有一个子针指向父类的对象,对于这个说法我表示怀疑,因为这样的话,那你创建一个对象的时候会有很多对象创建出来,这种设计方式太浪费内存。今天就来用JOL验证一下是否是这样的。(注:本次实验的对象大小是建立在指针压缩的情况下的,指针不压缩时不影响本实验的结果,只是对象的大小不同)

首先,你需要导入JOL包

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

  之后我们先看第一个问题:一个Object类对象占用多大的内存

public class JolTest {
    public static void main(String[] args) {
        Object o = new Object();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
    }
}

  执行上面的代码结果如下

 可以看到一个Object占有16个字节,前12个字节是对象头,后4个字节是java为了对齐使用的补充数据,一个java对象的大小总是8的整数倍

之后我们尝试创建一个类,包含一个int型的变量,看看他在内存中是什么样的

public class JolTest {
    public static void main(String[] args) {
        Object o = new Parent();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
    }
}

class Parent{
    private int age;
}

执行结果如下

仍然是16个字节,但是不同的是12-15这4位不在是alignment,而是int,我们知道int类型占有4个字节

之后我们写一个类继承Parent,看看他的情况

public class JolTest {
    public static void main(String[] args) {
        Object o = new Child();
        System.out.println(ClassLayout.parseInstance(o).toPrintable());
    }
}
class Parent{
    private int age;
}
class Child extends Parent{
    private int age;
}

 从执行结果中我们可以看出,子类中拥有一个对象Parent.age,并没有指向父类的指针,因此我们可以得出结论,创建子类对象时只会得到一个子类的对象,但是子类对象中会包含父类的属性,即使该属性是private的,即使该属性和父类的属性同名

现在不知得到了我想要的答案,而且有额外的以下三种收获:

1.如何计算一个对象的大小(启用指针压缩时):((12 + 自己属性的大小 + 自己所有祖先类的属性的大小 + 4)/ 8) * 8

2.另一个不支持深度继承的依据,不会使用的父类属性也会对对象的大小造成影响。

3.在需要严格控制的对象(一般是在项目中会大量创建的类对象)中,是使用继承还是组合需要考虑一下,毕竟继承可能会浪费属性,而组合会浪费对象头和alignment,如果仅从对象大小来考虑,如果继承的属性存在必要的,建议使用继承;如果全都是非必要的,可以使用组合,在需要该属性的时候再创建对象。

猜你喜欢

转载自www.cnblogs.com/fiftyonesteps/p/12554104.html