Java中如何去计算一个对象的内存占用?一个对象有哪些部分组成

  • 对象的组成部分
  • 1. 对象头
  • 1.1 MarkWord 固定4或者8个字节
  • 1.2 Klass Word 指向类的指针 4个字节
  • 1.3 数组长度array length 固定4或者8个字节
  • 2.2 实例数据
  • 2.3 对齐填充
  • 计算一个对象的内存占用






以HotSpot为例

对象的组成部分

对象的组成部分主要是三个部分:对象头、实例数据、对齐填充
其中对象头又分为三个部分:MarkWord、指向类的指针、数组长度(如果对象是数组的话,如果不是则没有此部分)

1. 对象头

1.1 MarkWord 固定4或者8个字节

在32位虚拟机中,占4个字节

java对象分配 java对象组成部分_开发语言

在64位虚拟机中,占8个字节

java对象分配 java对象组成部分_java对象分配_02


Mark Work存储的是对象自身运行时的数据,比如:锁标志位;是否偏向锁;GC分代年龄;对象的hashCode;获取到该锁的线程的线程ID;偏向时间戳(Epoch)等等。

1.2 Klass Word 指向类的指针 4个字节

对应JVM位数,如果是64位的那么占用8个字节,如果32位占用4个字节,在开启压缩的情况下可以压缩成8->4个字节。
Java对象存放在堆中,但其类信息存放在方法区中,所以Klass word指向该对象的类信息。

1.3 数组长度array length 固定4或者8个字节

如果当前对象是数组,才有此数组长度字段。
如果jvm是32bit,则数组长度是32bit;如果jvm是64bit,则数组长度是64bit

2.2 实例数据

具体的对象属性内存占用大小。
对象的实例数据就是对象在java代码中的属性(包括父类属性以及自己的属性)和值。

2.3 对齐填充

因为jvm要求Java对象占用内存的大小是8byte的倍数,因此需要把对象的大小补齐至8byte倍数。

计算一个对象的内存占用

<dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.9</version>
        </dependency>
public class WordFilter {
    private long aLong = 0L;
    private long bLong = 0L;
    private long cLong = 0L;
    private byte aByte;

    public static void main(String[] args) {
        System.out.println(ClassLayout.parseInstance(new WordFilter()).toPrintable());
    }

}

对象头部分等于 8+4 = 12个字节

实例数据大小 long (8x3) + byte (1x1)=25字节

由于 37不是8的倍数

对其填充为 40

java对象分配 java对象组成部分_jvm_03




如有错误欢迎指正