[principle of Java virtual machine] garbage collection algorithm (reachability analysis algorithm | CG Root example | twice marking before CG COLLECTION | finalize method example)





1, Reachability analysis algorithm


In heap memory, there is a root object GC root, and CG root objects are generally the following:

  • The reference object in the local variable table in the stack frame in the thread stack;
  • Static reference objects in the method area;
  • Constant reference objects in the method area;
  • The referenced object in JNI in the local method stack;

The root object CG Root points to object 1; Object 1 points to object 2 and object 3; Object 3 points to object 4;

As long as the objects in the whole chain are non garbage objects and cannot be recycled;

Objects that are not in the reference chain are garbage objects;


In the following figure, purple is the living object and white is the recyclable garbage object;





2, CG Root example


Find the CG Root object in the following program;

public class HelloWorld {

    public static HelloWorld mHelloWorld = new HelloWorld();

    public int add() {
        int a = 1;
        int b = 1;
        int c = a + b;
        return c;
    }

    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorld();
        helloWorld.add();
    }
}

The first 13 13 The helloWorld object in line 13 is a CG Root object, which meets the condition of "reference object in local variable table in stack frame in thread stack";

There are other reference objects in the helloWorld object. As long as the reference chain is not broken, the objects on the chain are non garbage objects;

Once helloWorld = null is executed; Statement, then the object and the following objects will have no reference chain, and the object and the objects below will become garbage objects;





3, Two marks before CG recovery


When an object is defined as a garbage object, it will not be recycled immediately. It is only given a death sentence, and garbage collection is not really implemented;

When the CG Root reference chain is broken, the object is unreachable;

The JVM will mark these unreachable objects once, then perform a filter and execute the finalize method of the object,

public class HelloWorld {
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
    }
}

The finalize method is a method called before the object is garbage collected by GC. This method cannot be guaranteed to be completed. The JVM will give the object a time limit to execute the finalize method within this time. Do not perform time-consuming operations in the rewritten method;

In the finalize method of the object, if you don't want to be recycled, you can add a reference chain again to let the CG Root object reference itself;


After that, the JVM will mark the unreachable object for the second time. At this time, if it is found that the object is still a garbage object, the object will be recycled directly;

The finalize method will only be called once. When the JVM marks the object for the second time, if it finds that the object is not referenced, it will be recycled directly and the finalize method will not be called again;





4, finalize method example


Create an object, assign A value to variable A, and then empty A, and the object becomes A garbage object;

In the finalize method, the object tries to save itself and assigns itself to A, so that the object becomes A non garbage object;

After calling the System.gc() method, you generally need to pause for a few seconds and wait for the finalize method to be called;


Here, A is set to null twice. The finalize method is called for the first time. The self rescue is successful and has not been recycled;

After the second null setting, the finalize method is no longer called and is recycled;


Code example:

public class HelloWorld {

    public static HelloWorld A;

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize Called");
        A = this;
    }

    public static void main(String[] args) throws InterruptedException {
        A = new HelloWorld();

        // Make object garbage
        A = null;

        // Garbage collection
        System.gc();
        // Due to the low priority of gc
        //      Wait 1000ms to see if finalize is called
        Thread.sleep(1000);

        // Before this GC call
        //      The finalize method was called first
        //      Added CG Root reference chain for object
        //      This method is called only once
        if (A == null) {
            System.out.println("Object is recycled");
        } else {
            System.out.println("The object was not recycled");
        }

        // Make object garbage
        A = null;

        // Garbage collection
        System.gc();
        // Due to the low priority of gc
        //      Wait 1000ms to see if finalize is called
        Thread.sleep(1000);

        // Call GC this time
        //      Directly judge whether the object has a reference chain
        //      The finalize method is no longer called
        //      If no reference chain is found, it can be recycled directly
        if (A == null) {
            System.out.println("Object is recycled");
        } else {
            System.out.println("The object was not recycled");
        }
    }
}

Execution results:

finalize Called
 The object was not recycled
 Object is recycled

Keywords: jvm

Added by leena on Sat, 04 Sep 2021 08:34:46 +0300