How HotSpot implements object survival judgment and garbage collection during GC

1. Enumerate the root node

Earlier, it was introduced that in the GC process, it is necessary to first determine whether the object is alive, and the reachability analysis algorithm is used to find the reference chain through the GC Roots node. The nodes that can be used as GC Roots are mainly global references (such as constants and static variables), and in the execution context (local variable table in the stack frame). So how to find the root node on the stack among so many global variables and local variable tables in the stack? Only a part of the data in the stack is of Reference type, and those data of non-Reference types are useless for finding the root node. If we scan the stack all over, it is quite a waste of time and resources. So to find the GC Roots root node by enumeration.

Reachability analysis is sensitive to execution time, which is reflected in the GC pause. During the analysis process, the object reference relationship cannot be constantly changing, which results in that all Java execution threads must be paused during GC. Therefore, the enumeration root Nodes must also be paused.

At present, the mainstream Java virtual machines use accurate GC. When the system stops, there is no need to globally scan the reference location. With the data structure of OopMap, the virtual machine can directly know where the object references are stored, so it can be quickly completed. Enumerate root nodes.

2. Safety point

There are many instructions for changing the content of OopMap, and it is not possible to generate a corresponding OopMap for each instruction. The HotSpot virtual machine generates an OopMap at specific locations, which are called "safe points". When the program is executed, it will only pause to start the GC when it reaches a safe point. Generally, instructions with the characteristic of "long execution" (such as method calls, loop jumps, exception jumps) will generate safe points.

How to make all threads run to a safe point and then stop during GC? Two options:

(1) Preemptive interrupt. (Few virtual machines use this method now)

There is no need for active cooperation of threads. All threads are interrupted when GC occurs. If it is found that the place where a thread is interrupted is not at a safe point, then the thread is resumed, and then it runs to a safe point.

(2) Active interrupt

When the GC needs to interrupt the thread, it does not directly operate on the thread, but sets a flag, so that each thread actively polls the flag, and if the interrupt flag is true, it will interrupt itself.

3. Safe area

The use of "safe point" seems to perfectly solve the problem of how to enter the GC. The safe point mechanism ensures that the program execution will encounter a safe point in a not too long time, thus entering the GC. However, when the program is not executing (that is, when the thread is in the Sleep or Blocked state), the thread cannot respond to the JVM's interrupt request and go to a safe point to interrupt and suspend, and the JVM will not wait for the thread to wake up again. area to resolve.

A safe area means that in a piece of code, the reference relationship will not change, and it is safe for GC to occur anywhere in this area. When the code executes to the safe area, it first identifies that it has entered the safe area, so if the JVM initiates GC during this time, it does not need to care about those threads that identify itself in the safe area. When the thread leaves the safe area, it will check Whether the system is performing a GC, and if so, wait until the GC is complete before leaving the safe area.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326393115&siteId=291194637