Daily sentence

We begin with confusion and end up with a higher level of confusion. — A.F. Chalmers

If the profile

This article focuses on the memory layout of the JVM and its associated dependencies and features, which will be supplemented by more detailed and in-depth analysis. For every “Java enthusiast”, if you want to explore its essence and reduce the doubts in your mind, the best way is to study the underlying principles, and the MEMORY management of the JVM is the unique charm of Java, but also the “unknown holy land” of developers, we slowly into this area.

JVM Memory layout

If you want to understand the memory management of the JVM, you need to know what the JVM memory consists of, as shown in the following figure

From the figure, we can clearly understand the relevant memory distribution structure. We find that the overall system is mainly composed of runtime data area and several other subsystems. Let’s take a look at the runtime data area first

Runtime data area

When a JVM runs a Java program, it divides the memory it manages into different data areas. There are differences between jdK1.8 and earlier versions.

Jdk1.6 architecture model

Jdk1.8 architecture model


As you can see from the details of the two versions above, the overall runtime data area can be divided into:

PC Register, VM Stack, Native Method Stack, Heap, Method Area, and Direct Memory.

  • The entire memory data area belongs to the current process, which owns all the resources and data. Direct memory is shared by all processes.
  • The stack and program counters are thread private, that is, each thread has its own area. Don’t interfere with each other.

Program Counter (PC Register)

The code is compiled into bytecode before the program executes, and the program counter is not the program counter (the address of the computer’s instructions) that our computer is made of, whereas the JVM’s PC is the indicator of the bytecode interpreter. It stores the address of the bytecode. (Basically points to the method area metadata and the first address of the object for calculation)

This stores the address of the bytecode being executed if the Java method is being executed, and undefined if the local method is being executed.

The bytecode interpreter works by changing the value of this counter to select the next bytecode instruction to be executed. Branches, loops, jumps, exception handling, thread recovery and other functions depend on this counter.

In a multi-threaded environment, the PC can also be guaranteed to return to the original thread position.

Note: The program counter is the only memory area that does not have an OutOfMemoryError, and its life cycle is created with the creation of a thread and dies with the end of the thread.

Java virtual machine stack

The virtual machine stack is the memory model of Java method execution. The data for each method call is passed through the stack. When each method is executed, a stack frame is created, pushed onto the stack, and when the method returns normally or throws an uncaught exception, the stack frame is removed

The stack frame:

  • Operand Stack: Memory model of operation variables, the maximum depth of which is determined at compile time (written to the max_stacks TAB of the method area code property). The elements of the operand stack can be any Java type, including long and double, and the 32-bit space on the stack is 1 and the 64-bit space is 2. When the method is first executed, the stack is empty, and as the method executes, various bytecode instructions fetch and unload data onto the stack.
  • Dynamic Linking: A stack frame holds a reference to the method it belongs to in the runtime constant pool to support Dynamic Linking during method invocation.
  • Method exit message (return Adress refers to the address of a bytecode instruction) : pushes a return value, if any, into the operand stack in the caller’s stack frame and points the PC value to the address of an instruction following the method call instruction
  • Local Variable table: Contains all variables during the execution of a method. The space needed for the local array of variables is allocated at compile time, and the size of the local array does not change during the run of the method. (Write max_locals to the method area code property)
  • Program counter: refers to the bytecode instruction being executed by the current thread, thread private.

Various basic data types and reference types Java stack can be compared to the data structure stack. The main content stored in the Java stack is the stack frame. Each function call will have a corresponding stack frame pushed into the Java stack, and after each function call, there will be a stack frame popped up. Y has two return methods in Java methods: throwing an exception and a return statement. Both methods return the stack frame to pop up.

Java heap memory

The Java heap is an area of memory shared by all threads and is created when the virtual machine is started. The sole purpose of this memory area is to hold object instances, and almost all object instances and arrays are allocated memory here. This area is also frequented by garbage collectors.

Java heap can also be subdivided into: new generation and old generation, permanent generation (method area) : more detailed: Eden space, From Survivor, To Survivor space (these three are the new generation)

In most cases, the object will be allocated in Eden first. After a Cenozoic garbage collection, if the object is still alive, it will enter S0 or S1 and its age will be increased by 1(the initial age of the object becomes 1 after Eden ->Survivor). When it reaches a certain age (15 by default), it is promoted to the old age.

Methods area

The method area, like the Java heap, is an area of memory shared by individual threads that stores information about classes loaded by the virtual machine, constants, static variables, just-in-time (JIT) compiled code, and so on. Although the Java Virtual Machine specification describes the method area as a logical part of the Heap, it has an alias called non-heap, which is supposed to distinguish it from the Java Heap.

For the implementation of the method area, the policies vary from virtual machine to virtual machine. In the case of our favorite HotSpot VIRTUAL machine, the design team implemented the method area using persistent bands and extended generational collection of GC to persistent bands. This design has the advantage of eliminating the need to write memory-management code specifically for the method area. In a real world scenario, however, such an implementation is not a good idea because it is more likely to run into memory overflow problems because of a permanent MAX cap.

It is also important to note that in the HotSpot VIRTUAL machine the permanent strip and heap are isolated from each other, but their physical memory is contiguous. And the garbage collector for the old and permanent bands is tied, so whoever is full will trigger both the permanent and the old GC.

After JDK1.8, the HotSpot VIRTUAL machine has removed the method area (permanent strip) and replaced it with the meta-space (moved into direct memory).

Run-time constant pool

The JDK1.8 JVM has removed the string constant pool from the method area and created an area in the Metadataspace to hold the runtime constant pool for class information, constant information, and constant pool information, including class data constants and numeric constants. Common reflection is the class information read from this method area, and the heap has memory space for a pool of string constants.


Object creation process

The runtime data area for Java8 is shown in figure 1. The permanent generation is gone, and what is left is an area called a metadata area. The meta space in 1.8 is no longer physical memory contiguous to the heap, but instead uses Native memory. The meta space uses local memory, which means that OOM errors will not occur as long as there is enough local memory. By default, the meta-space size is unlimited, but the JVM also provides parameters to control its use.

-XX:MetaspaceSize
    class metadataThe initial space quota tobytesIn units, reaching this value triggers garbage collection for type offloading, whileGCThe value is adjusted: if you free a lot of space, lower the value appropriately; If you free up very little space, then in no moreMaxMetaspaceSize(if set), increase the value appropriately. -XX:MaxMetaspaceSizeCan I do forclass metadataThe maximum space allocated. The default is unlimited. -XX:MinMetaspaceFreeRatioGCAfter that, the smallestMetaspaceThe percentage of remaining space capacity is reduced to zeroclass metadataGarbage collection due to space allocation. -XX:MaxMetaspaceFreeRatioGCAfter that, the biggestMetaspaceThe percentage of remaining space capacity is reduced to zeroclass metadataFree space resulting in garbage collection.Copy the code
  • (1) When the JVM encounters a new instruction, our constant pool queries whether there is a symbolic reference to this class (fully qualified class name). If there is no indication that this class has not been loaded and parsed, we need to load the resolution, and at the same time add symbolic reference to the constant pool, add class information in the method area.
  • (2) Then allocate memory in two ways (pointer collision and free list)
  • (3) After the memory allocation is completed, the VIRTUAL machine needs to initialize the allocated memory space to zero (excluding the object header). This step ensures that the object instance fields can be used directly in Java code without assigning initial values, and the program can access the zero values corresponding to the data types of these fields.
  • (4) Set the object header, which stores: the object is the instance of the class, how to find the metadata information of the class, the object’s hash code, the object’s GC generation age and other information, whether to enable biased locking, etc.
  • (5) Execute init to initialize the object as the programmer wants it to (i.e., constructor initialization).

Object access location

(1) Handle method: If handle is used, a block of memory will be divided into The Java heap as the handle pool. Reference stores the handle address of the object, and the handle contains the specific address information of the instance data and type data of the object.

(2) Direct pointer: If direct pointer access is used, then the layout of the Java heap object must consider how to place the information related to the access type data, and the direct stored in reference is the address of the object.

Both object access methods have their own advantages. The biggest advantage of using handles for access is that reference stores a stable handle address and only changes the instance data pointer in the handle when the object is moved.Reference itself does not need to be modified.The biggest advantage of using direct pointer access is fast speed, it saves the time cost of a pointer location.

Out of memory

  • StackOverFlowError: A StackOverFlowError is thrown when a thread requests a stack depth that exceeds the current maximum depth of the Java virtual machine stack if the memory size of the Java virtual machine stack does not allow dynamic scaling.
  • OutOfMemoryError: An OutOfMemoryError is thrown if the memory size of the Java virtual machine stack allows dynamic expansion and the memory is exhausted when the thread requests the stack.

Class loading system

Is responsible for loading class information from the file system or network in a memory space called the method area

Direct memory

Direct memory is not part of the running data region of the virtual machine, nor is it defined in the VIRTUAL machine specification, but it is frequently used by reads and writes and may cause OutofMemoryErrors. The allocateDirect method in Java NIO can use direct memory directly, which can significantly improve read and write speed. Java8’s MetadataSpace MetadataSpace uses direct memory, whereas previously the method area was logically part of the heap and used JVM memory space.

Local method stack

The difference between the local method stack and the Java stack is that Java native methods can be directly called, that is, methods modified by NATIVE in JDK can call the local memory model, and the thread is private

Virtual machine stacks, local method stacks, and program counters are thread isolated. The method area and heap are data areas shared by all threads.