Memory layout

According to the Java Virtual Machine Specification (JavaSE version 7), the Java Virtual Machine at runtime divides the memory it manages into the following different data areas, each with its own user and creation and destruction time.

Program counter

The program counter is an indicator of the line number of the bytecode executed by the current thread, indicating the next byte code instruction to be executed. Branching, loop, jump, exception handling, and thread recovery all need to rely on the program counter to complete.

Because each thread executes instructions differently, the program counter is thread private.

The virtual machine stack

The virtual machine stack is also thread-private, with each thread executing a method creating a stack frame to store local variables, operand stacks, dynamic links, method exits, and so on.

From the time a method is called to completion, it corresponds to the push and exit of a stack frame.

Local method stack

The functions of the local method stack are similar to that of the virtual machine stack, except that the virtual machine stack serves Java methods while the local method stack serves Native methods

The Java heap

The heap should be the largest amount of memory managed by the Java virtual machine. It is also an area of memory shared by all threads and is usually the focus of garbage collection. The purpose of setting the heap is to store object instances. Almost all object instances are allocated here, such as object instances and arrays, but not absolutely.

The heap includes: the new generation and the old. The new generation includes Eden, From Survivor and To Survivor.

Garbage collection algorithms have different collection measurements for each region, and most collectors today use generational collection algorithms

Methods area

The method area, like the Java heap, is shared by threads and is used to store class information, constants, static variables, and code compiled by the just-in-time compiler. The method area, also called non-heap, is used to distinguish between Java heaps.

Method areas have been called permanent generations before.

The purpose of partitioning is to facilitate garbage collection, depending on the implementation of the garbage collector, some of which extend into the method area and are managed like the Java heap.

Runtime constant pool

The runtime constant pool is part of the method area that stores class versions, fields, method and interface descriptions, as well as various literal and symbolic references generated by the compiler.

Direct memory

Direct memory is independent of the above memory areas. Some I/O operations will place data in direct memory to avoid data replication, such as Java’s DirectByteBuffer. This area of memory is not managed by the Java heap but is also limited by the total memory size and memory addressing space.

HotSpot object layout

Object creation

Java creates objects by simply using the new keyword, but the process of creating objects is complicated. The virtual new directive is created by checking whether the parameter of the directive can find a symbolic reference in the constant pool, and whether the symbolic reference represents a class that has been loaded, parsed, and initialized.

After the class load passes, the VIRTUAL machine allocates memory for the new object. There are two situations when allocating memory. One is that the Java heap is a regular memory space, and the other is that the Java heap is not a regular memory space. A neat memory space requires a pointer collision, which is moving the free memory to one side, moving the used memory to the other side, and then pointing that pointer to the free side.

Irregular allocation of space requires the use of free list, free connection simple understanding is to put free memory block in a list, need to use the list to apply.

Object memory layout

In the HotSpot virtual machine, the layout of objects can be divided into three areas: object headers, instance data, and alignment padding.

  • Object header: Contains two parts, the first part is used to store the runtime data of the object itself, such as hash, GC generation age, lock status flag, thread-held lock, preferred thread ID, preferred time, etc. This piece of data is called the “Mark Word”. The second part is used to store type Pointers, which are Pointers that an object points to its class metadata and are used by the VIRTUAL machine to determine which class the object is an instance of.

  • Instance data: Instance data is the actual valid information stored by an object. It is the content of various types of fields defined in the program code, including those inherited by the parent class

  • Aligned padding: Some virtual machine implementations do not have this section, it only exists as a placeholder

Object

The virtual machine only specifies that the reference type is a reference to an object, and does not specify how to locate the object. So there are two ways to locate the object: using a handle or direct pointer

  • Use handle: Divide a handle pool in the Java heap. Reference stores the address of the object’s handle, and the handle contains the pointer to the object’s instance data. The main advantage of this approach is that the reference is a stable handle address, and the reference does not need to be changed if the object is moved.

  • Use direct Pointers: The direct object stored in Reference is the address of the object in the Java heap. The biggest advantage of this method is that access speed, do not need to intermediate second pointer access.

Out of memory

If memory is allocated when there is not enough memory, each region will throw an exception, the most common is OutOfMemoryError (i.e. OOM).