Memory layout of Java objects

Posted by ca87 on Fri, 31 Dec 2021 20:28:04 +0100

Overview of object memory storage layout

In the JVM virtual machine, the storage layout of objects can be divided into three parts: Object Header, Instance Data and Padding.

Let's talk about each part in detail.

Object Header

The header of the virtual machine mainly includes the run-time data (Mark Word) and type pointer of the storage object itself. There will be an additional array length based on these two in the array object. This is what the object header contains.

Mark Word

Mark Word is the runtime data used to store the object itself. Not the same in 32-bit and 64 bit systems (compression pointer is not turned on). In different lock states of objects, they are also different. The following figure indicates the content of Mark Word:

I drew this by hand. You can draw it yourself.

Type pointer (Klass Word)

Klass Word is the pointer of the object to its type metadata. The Java virtual machine uses this pointer to determine which class the object is an instance of.

If the object is a Java array, a piece of data for recording the length of the array will be added to the object header.

Instance Data

The instance data part is the effective information actually stored by the object (the field content of each type defined in the program), which will be recorded in the instance data.

Align padding

Aligned padding only serves as a placeholder. The automatic memory management system requires that the starting address must be an integer multiple of 8 bytes. Filling it is to fill the object to an integer multiple of 8 bytes.

experiment

Now we need to import a dependency to provide support

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

Then let's use classlayout parseInstance(a). To printable() to view the layout of the object:

View the layout of empty objects

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

First, Mark Word with an Object header has 64bit, 8bytes, and then a type pointer of 4bytes. Because it is an empty Object, there is no instance data, and then align and fill 4bytes. Therefore, it is concluded that the Object object is 16bytes.

Then we create an object and look at its layout

First, create an object without properties

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


class B {

}

This is the same as creating an Object, so I won't talk about it.

Add properties of basic type for B object

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


class B {
    boolean  b = true;
    int anInt = 1;
    int bIn = 2;
}

 

Add basic type attributes to the object, the instance data will appear in the object layout, and the instance data is continuous. Besides, Boolean data accounts for 1 byte, other data types account for 4 bytes.

Add non basic type data for B object

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


class B {
    boolean  b = true;
    int anInt = 1;
    int bIn = 2;
    String s = "aaaa";
    JsonController jsonController = new JsonController();
}

After filling non basic data types for B objects, a Padding gap will appear in the instance data module. Here, each data is filled to 4 bytes, and the data of non basic types is also 4 bytes.

To sum up, there must be two conditions for the occurrence of padding gap: the instance data is not enough 4 bytes, and there are non basic type data attributes in the object.

Finally, let's look at array objects

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

This is an array object initialized to a length of 100. We can see that there is an additional module recording the array length of 4 bytes in the object header of the array object, and a memory space of 4 bytes has been opened up for the array later.

The memory layout of the object is almost here. To sum up

The object memory layout is mainly composed of Mark Word (generally 12bytes, array object 16bytes), instance data (depending on how the object is determined) and alignment filling (aligned as a multiple of 8bytes).

Thank you for watching and making progress together!

Topics: Java