When an object is created in Java with the new keyword, the specified size of memory space is allocated to the new object in different ways, depending on whether the heap is neat or not (which is influenced by the garbage collector). This part of the memory space is divided into “object header”, “instance data”, and “alignment padding”. After the object is initialized, it is usually selected as a “direct pointer” or “handle” to provide external access to the object in order to make it usable.

1. Memory allocation policy

When a new object is created using the new keyword, the virtual machine first identifies the class symbol reference and performs the class loading process (skip this step if the class has already been loaded, see Chapter 7 for details). After that, the new object needs to be allocated its available memory, which is located on the heap.

The heap is the workspace of the garbage collector. After garbage collection is performed, uncollected objects are irregularly allocated in the heap, creating a large amount of debris space, as follows:

Such heap memory is said to be “irregular” and requires a “Free List” to keep track of what memory is available and how big it is to allocate to objects of different sizes.

Some garbage collectors have the ability to “clean up” the “dead” objects and then store the living objects together, resulting in a “neat” heap memory.

At this point, there is a sharp dividing line between used and unused memory, called the “tipping point.” To allocate memory to a new object, you simply shift The critical point a certain distance toward free memory. This method of allocating memory is known as “bumping The Pointer.”

Of course, the act of creating objects is likely to be executed concurrently, and the virtual machine provides two ways to solve the problem of allocating memory concurrently:

  • CAS+ Retry after failure;
  • In the last article, I mentionedThread Local Allocation Buffer, TLAB, can be passed-XX: +/-UseTLABTurn on or off. This mechanism preallocates an area of memory on the heap for each thread, called”Local buffer“, when the buffer is used up, synchronization orCASTo allocate a new buffer. There is no need to worry about concurrency when using memory space in buffers.

2. Object memory layout

Memory allocated to new objects is divided into “object header”, “instance data”, and “alignment padding” sections.

2.1 object head

The object header contains two parts of information: one is the runtime data of the object itself, including hash codes, generational information, lock flags, and so on, and is called the Mark Word. The other part is the type pointer.

2.1.1 Mark Word

For a 32-bit VM and a 64-bit VM, the length of the data is 32 bits and 64 bits respectively (compression is not enabled). Mark Word is designed as a dynamically defined data structure because the object runtime data is much longer than 32 or 64 bits. The following uses a 32-bit VM as an example:

2.1.2 Type Pointers

This part is a pointer to the metadata of the object’s type. However, finding an object’s type metadata does not necessarily require going through the object itself (see the “Handles” section of this article), so not all VMS have a storage type pointer in the object header.

2.1.3 Supplementary: Array length

If the object is an array, there must also be an area in the object header to store the length of the array so that the virtual machine can identify the size of the object.

2.2 Instance Data

This section stores information about all fields of the object, both inherited and self-defined. The order in which fields are stored is affected by the virtual machine allocation policy parameter –XX: FieldsAllocationStyle and the order in which fields are defined in the source code. The default field assignment order for the HotSpot virtual machine is:

  1. double/long;
  2. int;
  3. short/char;
  4. byte/boolean;
  5. Ordinary Object Pointers;

If the +XX:CompactFields argument is true (the default is true), narrow variables in a subclass are also allowed to be inserted into the gap between variables in the parent class to save space.

2.3 Alignment and Filling

The HotSpot virtual machine requires that the starting address of objects must be an integer multiple of 8 bytes, so any object must be an integer multiple of 8 bytes in size, and objects that do not meet this condition will be populated using the “aligned fill” area.

3. Object access mode

In the Java Virtual Machine Specification, reference type is only defined as a reference to an object, and there is no specific way to access and locate an object with reference type. Therefore, in mainstream virtual machines, there are “direct pointer” and “handle” methods to accomplish this work.

3.1 Direct Pointer

Reference Indicates the address of the object directly stored in reference. This approach requires the object header to have “type pointer” information so that references, objects, and types can be related.

Direct Pointers are efficient in that they can access specific information about an object in a single location. The HotSpot virtual machine also uses a “direct pointer”.

3.2 handle

An area of the heap memory is divided as a “handle pool”. The data units stored in the pool are also called “handles”.

The handle contains address information about the object itself and its type data, whereas reference stores the address of the handle itself. As you can see, using the handle method to access the object requires two positioning operations, which is inefficient. With handles, however, the header does not contain the type pointer information. In addition, when the address of the object changes after the collection operation is completed with the garbage collector with the “collation” function, only the address of the pointer that accesses the object instance needs to be changed in the handle, rather than the reference itself, which is also an advantage of the handle.