This article mainly talks about Java memory allocation and recycling mechanism, mainly including Javaruntime data area, object creation, garbage collection algorithm With Recycling Strategy.
Refer to the PHP Chinese website course "JAVA Elementary Introduction Video Tutorial". The author only summarizes and illustrates the culture based on the content in the tutorial. This part of the content is almost all comprehensible. In order to facilitate understanding and memory, it is presented in the form of pictures, texts or tables as much as possible.
The following figure is a memory diagram of the Java virtual machine when it is running:
From the picture we can see that Java memory is divided into 6 parts:
Program counter: Each thread has an independent program counter . The counter can be regarded as a line number indicator of the bytecode executed by the current thread. When the bytecode interpreter works, it changes the value of this counter to select the next bytecode instruction, branch, loop, jump, exception handling, that needs to be executed. Basic functions such as thread recovery rely on this counter.
Java virtual machine stack: The virtual machine stack is private to the thread, The life cycle is the same as the thread. The virtual machine stack describes the memory model for Java method execution. When each method is executed, a stack frame is created to store local variable tables, operand stacks, dynamic links, and methods. Export and other information. The process from the call to the completion of execution of each method corresponds to the process from pushing a stack frame into the virtual machine stack to popping it out.
Local method stack: It plays a similar role to the virtual machine stack. The difference is that the virtual machine stack serves Java method execution, and the local method stack serves Native methods.
Heap: An area shared by all threads. Created when the virtual machine starts, almost all object instances are allocated on the heap. The Java heap can also be subdivided into: the new generation and the old generation. In more detail, there are Eden space, From Survivor space, and To Survivor space. However, no matter how it is divided, all object instances are stored. The purpose of further division is to better reclaim memory or allocate memory faster.
Method area: The method area is a memory area shared by each thread. It is mainly used to store class information and constants,# that have been loaded by the virtual machine. ##staticVariables, on-the-fly compiled code and other data. This area, like the Java heap, does not require continuous memory and can be fixed or expandable. You can also choose not to implement garbage collection. The memory recycling target in this area is mainly for the recycling of constant pools and unloading of types. Garbage collection behavior rarely occurs in this area.
interface, the Class file also contains a constant pool, which is used to store various data generated during compilation. The literal characters and symbols refer to . This part of the content is stored in the runtime constant pool in the method area after the class is loaded.
Direct memory is also called off-heap memory. It is not part of the data area when the virtual machine is running. The NIO class was introduced after JDK1.4, which is an I/O method based on channels and buffers. It can use the Nativefunction library to directly allocate memory outside the heap, and then store it through The DirectByteBuffer object in the Java heap operates on this memory as a reference. This can significantly improve performance and avoid copying data back and forth between the Java heap and Native heap.
Data Area | Summary | Thread Sharing |
---|---|---|
Program Counter | Line number indicator of the bytecode executed by the current thread | No |
Virtual machine stack | Execution for Java method Create a stack frame to store local variables, operand stacks, dynamic links, method exits and other information | No |
Local method stack | And virtual machine stack Similarly, serving Native methods | No |
Heap | Store object instances | Yes |
Method area | Stores loaded class information, constants, static variables, instant compiled code and other data of the virtual machine | is |
Runtime constant pool | Part of the method area, which stores literals and symbol references generated during compilation | is |
direct memory | Memory allocated outside the heap has high performance and is not limited by the size of the Java heap | is |
The above picture is the complete flow chart of object creation, which will be explained in detail next.
When the virtual machine receives the new instruction, it checks whether the parameters of this instruction can locate a symbol reference of a class in the constant pool, and Check whether the class represented by this symbol reference has been loaded, parsed and initialized. If not, the class loading process must be performed first.
After the class loading is completed, the space required for object allocation can be determined. If the memory in the Java heap is absolutely regular, with used memory stored on one side and free memory stored on the other side, with a pointer in the middle as an indicator of the demarcation point, then allocating memory is just a matter of moving the pointer toward the free space by a certain amount. The distance between objects is equal in size. This allocation method is called "pointer collision". If the memory in the Java heap is not regular, and free memory and used memory are interleaved, the virtual machine must maintain a list to record which memory blocks are available, and find out enough space from the list to allocate when allocating Object instance and update records on the list. This allocation method is called "free list". Which allocation method is used is usually determined by whether the virtual machine's garbage collector has a compaction function.
When dividing the available space, you also need to consider whether it is thread safe when allocating space for object instances. To ensure thread safety, there are two options. One is to synchronize the action of allocating memory space. In fact, the virtual machine uses CAS with failure retry to ensure the atomicity of the update operation. The other is to divide the memory allocation action into different spaces according to threads. Each thread pre-allocates a small piece of memory in the Java heap, called Local Thread Allocation Buffer(Thread Local Allocation Buffer, TLAB). Which thread wants to allocate memory will allocate it on the TLAB of that thread. Synchronization locking is only required when the TLAB is used up and a new TLAB is allocated.
After the memory allocation is completed, the virtual machine will initialize the allocated memory space to zero value (excluding the object header), ensuring that the instance field of the object is in Java It can be used directly in the code without assigning an initial value.
The virtual machine puts the information of the object into the object header of the object.
Execute Constructor
The memory layout of an object is divided into three parts:
Object header It mainly includes two parts of information:
One part is used to store the object's own runtime data, such as hash code, GC generation age, lock Status flag, lock held by the thread, biased thread ID, biased timestamp , etc.
The other part is the type pointer, which is the pointer of the object to its class metadata. The virtual machine uses this pointer to determine which class the object is an instance of. If the object is a Javaarray, then there must be a piece of data recording the length of the array in the object header.
The instance data part is the effective information actually stored by the object, and it is also the content of various types of fields defined in the program code. Everything inherited from the parent class and defined in the subclass needs to be recorded.
Alignment padding only serves as a placeholder. HotSpot VM's automatic memory management system requires that the object starting address be an integer multiple of 8 bytes, so the object size must be an integer multiple of 8 bytes. When the object instance data part is not aligned, it needs to be completed by alignment padding.
The Java virtual machine determines whether the object is alive through reachability analysis . The basic idea of this algorithm is to use a series of objects called "GC Roots" as the starting point, and search downward from these nodes. The path traveled by the search is called a reference chain. When an object reaches GC Roots The object is unavailable when it is not connected to any reference chain. As shown in the figure,
object5, object6, and object7 are related to each other, but the GC Roots are unreachable, so they are judged to be recyclable objects.
Mainstream Java virtual machines almost no longer use reference counting to manage memory.
If the object does not have a reference chain connected to GC Roots after the reachability analysis, it will be marked for the first time and filtered once. The filtering condition is whether it is necessary for this object to execute the
finalize() method. When the object does not cover the finalize() method, or the finalize() method has been called by the virtual machine, the virtual machine treats these two situations as "no need to execute". If this object is determined to be necessary to execute the finalize() method, then this object will be placed in the F-Queue
queue, which will be automatically created by the virtual machine later with low priorityThe Finalizer thread executes the finalize() method. The GC performs a second small-scale mark on the object in the F-Queue. If the object is re-associated with any object on the reference chain, it will be removed from the "soon to be recycled" collection during the second mark. Otherwise the object will really be recycled.
Deprecated constants and Useless classes.
Mark-Sweep algorithm(Mark-Sweep):The algorithm is divided into two stages: "marking" and "clearing": first mark the objects that need to be recycled, and after the marking is completed, the marked objects will be recycled uniformly. It has two main shortcomings: First, it is
efficiency issue, both the marking and clearing processes are not very efficient. The second is space problem. After the mark is cleared, a large number of discontinuous memory fragments will be generated. Too many fragments may cause insufficient memory space to be found when a larger object is allocated, and a garbage collection action must be triggered in advance.
:Copy Algorithm Divide the available memory into two equal-sized blocks according to capacity, and only use one block at a time. When a block of memory runs out, copy the surviving
objects to another block, and then clean up the used memory space at once. This allows the entire half area to be recycled every time, and there is no need to consider memory fragmentation when allocating memory. Just move the top pointer of the heap and allocate memory in order. Simple implementation,Run efficiently. It's just that this algorithm reduces the memory to half of the original , which is more expensive.
Mark-Compact Algorithm (Mark-Compact) :
The marking process is the same as the "mark-clear" algorithm, but instead of directly cleaning up recyclable objects, all surviving objects are moved to one end, and then the memory outside the end boundary is directly cleaned up
4.Generational Collection Algorithm
Business The garbage collection of virtual machines adopts a generational collection algorithm, which divides the memory into several blocks according to the object survival cycle. The Java heap is divided into New Generation and Old Generation, so that appropriate collection algorithms can be used according to the characteristics of the era. A large number of objects die during each garbage collection in the new generation, so use the replication algorithm. The survival rate of objects in the old generation is high and there is no extra space for allocation guarantee, so it is suitable to use the "mark-clean" or "mark-organize" algorithm for recycling.
Objects are prioritized in the Eden partition:
In most cases, objects are allocated in the new generation Eden area. When the Eden area does not have enough space to allocate, the virtual machine initiates a Minor GC. After GC, the object tries to be put into the Survivor space. If the Survivor space cannot put the object into it, it can only be transferred to the old generation in advance through the space allocation guarantee mechanism.
Large objects enter the old generation directly:
Large objects refer to Java objects that require a large amount of continuous memory space. The virtual machine provides the -XX:PretenureSizeThreshold parameter. If the object is larger than this setting value, the object will be allocated directly in the old generation. This can avoid a large amount of memory copying in the Eden area and the two Survivor areas in the new generation.
Long-term surviving objects enter the old generation:
The virtual machine defines an object age counter for each object. If the object is born in Eden and still survives after a Minor GC, and can be accommodated by the Survivor, it will be moved to the Survivor space, and the object age is set to 1. After each Minor GC, the object still survives in the Survivor area, and the age Just add one, and when the age reaches the value set by the -XX:MaxTenuringThreshold parameter, it will be moved to the old generation.
Dynamic age judgment:
The virtual machine does not always require that the age of the object must reach the value set by -XX:MaxTenuringThreshold before it will move the object to the old generation. If the sum of the sizes of all objects of the same age in the Survivor is greater than half of the Survivor space, objects whose age is greater than or equal to this age can directly enter the old generation.
Space allocation guarantee:
Before Minor GC, the virtual machine checks whether the maximum available continuous space in the old generation is greater than the total space of all objects in the new generation. If the condition is true, then Minor GC is established. If not, the virtual machine checks whether the HandlePromotionFailure setting value allows guarantee failure. If allowed, it will continue to check whether the maximum available continuous space in the old generation is greater than the average size of objects moved to the old generation. If it is greater, a Minor GC will be tried. If it is less than, or the HandlePromotionFailure setting value does not allow risk, a Full GC will be performed.
New generation GC (Minor GC): Garbage collection action that occurs in the new generation. Because most Java objects die day and night, Minor GC is very frequent and the recycling speed is relatively slow. quick.
Old generation GC (Major GC/Full GC): Garbage collection actions that occur in the old generation. Major GC is often accompanied by at least one Minor GC. The speed of Major GC is generally more than 10 times slower than Minor GC.
The above is the detailed content of Detailed explanation of Java memory allocation and recycling mechanism (picture). For more information, please follow other related articles on the PHP Chinese website!