Reachability algorithm

1, Reachability analysis algorithm

In Java, the Reachability Analysis is used to determine whether an object is alive or not. The basic idea of this algorithm is to start with some objects called GC Roots, and start to search down from these nodes. The path that the search passes through is called reference chain. When there is no reference chain between an object and GC Roots (that is, it is impossible to reach from GC Roots node to this node), the object is proved to be unavailable.

Reachability analysis algorithm to determine whether the object can be recycled


As shown in the figure above, object1~object4 are reachable to GC Root, indicating that they cannot be recycled, object5 and object6 are not reachable to GC Root nodes, indicating that they can be recycled.
In Java, the objects that can be used as GC Root include the following:

  • Objects referenced in virtual machine stack (local variable table in stack frame)
  • Objects referenced by class static properties in method area
  • Object referenced by constant in method area
  • Objects referenced by JNI (commonly known as Native methods) in the local method stack

2, The finalize() method finally determines whether the object is alive or not

Even for the unreachable objects in the reachability analysis algorithm, they are not "undead". At this time, they are temporarily in the "Probation" stage. To truly declare the death of an object, at least they need to go through the process of re marking.
The premise of tagging is that the object does not have a reference chain connected to GC Roots after reachability analysis.
1. Mark and filter for the first time.
The filter is based on whether it is necessary for this object to execute the finalize() method.
When the object does not overwrite the finalize method, or the finzlize method has been called by the virtual machine, the virtual machine regards both cases as "unnecessary execution", and the object is recycled.
2. Second marking
If the object is judged to be necessary to execute the finalize () method, the object will be placed in a queue named F-Queue, which will be executed later by a low priority Finalizer thread automatically established by a virtual machine. The so-called "execution" here means that the virtual opportunity triggers the method, but does not promise to wait for it to run. The reason for this is that if an object in the finalize () method executes slowly, or a life and death cycle (more extreme) occurs, it is likely to cause other objects in the F-Queue queue queue to be permanently waiting, or even cause the entire memory recovery system to crash.
The finalize() method is the last chance for an object to escape the fate of death. Later, GC will mark the object in F-Queue for a second time. If the object wants to save itself successfully in finalize(), just re establish the relationship with any object in the reference chain, such as assigning itself to a class variable or a member variable of an object, then in the second time When marked, it removes the collection that is about to be recycled. If the object doesn't escape at this time, it's basically recycled.

3, Java references

It can be seen from the reachability algorithm that whether the object is reachable is related to "reference". Under what circumstances can we say that an object is referenced and what exactly does the reference represent?
After JDK 1.2, Java extends the concept of reference, which can be divided into the following four categories:

  • Strong reference
  • Soft reference
  • Weak reference
  • Phantom reference

These four kinds of references weaken from top to bottom

3.1 strong reference

Strong reference is a reference that is common in program code, such as Object obj = new Object(). As long as the strong reference is in, the garbage collector will never collect the referenced object. That is to say, we would rather run out of memory than recycle these objects.

3.2 soft reference

Soft reference is used to describe some useful but not necessary objects. In Java, it is represented by java.lang.ref.SoftReference class. For objects associated with soft references, the JVM will recycle them only when there is insufficient memory. Therefore, this can be used to solve the problem of OOM, and this feature is very suitable for cache: such as web page cache, image cache, etc.

import java.lang.ref.SoftReference;
 
public class Main {
    public static void main(String[] args) {
         
        SoftReference<String> sr = new SoftReference<String>(new String("hello"));
        System.out.println(sr.get());
    }
}

3.3 weak references

Weak references are also used to describe unnecessary objects. When the JVM garbage collection, regardless of the memory, the objects associated with weak references will be recycled. In Java, it is represented by the java.lang.ref.WeakReference class. Here is an example:

import java.lang.ref.WeakReference;
 
public class Main {
    public static void main(String[] args) {
     
        WeakReference<String> sr = new WeakReference<String>(new String("hello"));
         
        System.out.println(sr.get());
        System.gc();                //Notify the gc of the JVM for garbage collection
        System.out.println(sr.get());
    }
}

3.4 virtual reference

Virtual reference is different from the previous soft reference and weak reference, it does not affect the life cycle of the object. In Java, it is represented by the java.lang.ref.PhantomReference class. If an object is associated with a virtual reference, it can be recycled by the garbage collector at any time, just as no reference is associated with it.
Note that the virtual reference must be associated with the reference queue. When the garbage collector is ready to recycle an object, if it finds that it has a virtual reference, it will add the virtual reference to the reference queue associated with it. The program can know whether the referenced object will be garbage collected by judging whether the virtual reference has been added to the reference queue. If the program finds that a virtual reference has been added to the reference queue, it can take necessary actions before the memory of the referenced object is recycled.

 

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
 
public class Main {
    public static void main(String[] args) {
        ReferenceQueue<String> queue = new ReferenceQueue<String>();
        PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
        System.out.println(pr.get());
    }
}

3.5 further description of soft reference and weak reference

In the SoftReference class, there are three methods, two construction methods and a get method (WeakReference is similar):

public class SoftReference<T> extends Reference<T> {

    /**
     * Timestamp clock, updated by the garbage collector
     */
    static private long clock;

    /**
     * Timestamp updated by each invocation of the get method.  The VM may use
     * this field when selecting soft references to be cleared, but it is not
     * required to do so.
     */
    private long timestamp;

    /**
     * Creates a new soft reference that refers to the given object.  The new
     * reference is not registered with any queue.
     *
     * @param referent object the new soft reference will refer to
     */
    public SoftReference(T referent) {
        super(referent);
        this.timestamp = clock;
    }

    /**
     * Creates a new soft reference that refers to the given object and is
     * registered with the given queue.
     *
     * @param referent object the new soft reference will refer to
     * @param q the queue with which the reference is to be registered,
     *          or <tt>null</tt> if registration is not required
     *
     */
    public SoftReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
        this.timestamp = clock;
    }

    /**
     * Returns this reference object's referent.  If this reference object has
     * been cleared, either by the program or by the garbage collector, then
     * this method returns <code>null</code>.
     *
     * @return   The object to which this reference refers, or
     *           <code>null</code> if this reference object has been cleared
     */
    public T get() {
        T o = super.get();
        if (o != null && this.timestamp != clock)
            this.timestamp = clock;
        return o;
    }

}

The get method is used to get the reference of the object associated with the soft reference. If the object is recycled, null is returned.

When using soft reference and weak reference, we can notify the JVM to recycle garbage through System.gc(). However, it should be noted that the JVM will not execute immediately even if the notification is sent, that is to say, this sentence cannot ensure that the JVM will recycle garbage at this time.

3.6 virtual reference further explains:

There is a constructor in a virtual reference, and you can see that it must exist with a reference queue. The get() method always returns null because virtual references are never reachable.

public class PhantomReference<T> extends Reference<T> {

    /**
     * Returns this reference object's referent.  Because the referent of a
     * phantom reference is always inaccessible, this method always returns
     * <code>null</code>.
     *
     * @return  <code>null</code>
     */
    public T get() {
        return null;
    }

    /**
     * Creates a new phantom reference that refers to the given object and
     * is registered with the given queue.
     *
     * <p> It is possible to create a phantom reference with a <tt>null</tt>
     * queue, but such a reference is completely useless: Its <tt>get</tt>
     * method will always return null and, since it does not have a queue, it
     * will never be enqueued.
     *
     * @param referent the object the new phantom reference will refer to
     * @param q the queue with which the reference is to be registered,
     *          or <tt>null</tt> if registration is not required
     */
    public PhantomReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }
}

Reference resources

Tags: Programming Java jvm JDK

Posted on Thu, 16 Jan 2020 07:18:39 -0500 by f1r3fl3x