JVM Quest: four kinds of reference, the object of life and death

This series of notes is mainly based on "in-depth understanding of the Java Virtual Machine: JVM advanced features and best practices 2nd Edition" is a book of reading notes.

Java virtual machine memory area, the program counter, stack and Java native method stacks thread is privately owned, with the threads born with the threads off, so the memory allocation and recovery of these areas have certainty, so the main inquiry memory allocation and recovery Java heap and method area.

Java heap

In the Java heap storage of all object instances, the garbage collector in front of the heap for recycling, the first thing is to determine which of these objects are still alive and which are dead (ie will not be used to object).

Cited in Java

In JDK1.2 before and that the definition of reference is this: If the value represented by a stored in memory is another piece of memory starting address, said to represent a piece of memory references (reference). But the relatively narrow definition of an object can only be referenced and not referenced two states. There is such a "tasteless gesture" of the object: When sufficient memory space, you can remain in memory, if memory after garbage collection is very tight, you can discard these objects. Many caching features are consistent with this scenario.

In JDK1.2 later, the concept was expanded references, the references into strong references (Strong Reference), soft references (Soft Reference), weak references (Weak Reference), virtual reference (Phantom Reference) 4 species, four species cited strength in descending order:

  • A strong reference (Strong Reference) is ubiquitous in the code, similar to the "Object obj = new Object () " of such a reference, as long as there are strong references, the garbage collector will never recover the object being referenced.

  • Soft references (Soft Reference) is used to describe a useful non-essential objects. Soft references are associated, before the system is going to happen out of memory, these objects will be secondary recovery. If this recovery has not enough memory, memory overflow exception will be thrown. The above mentioned "tasteless gesture," the objects belong to soft references.

  • Weak references (Weak Reference) is used to describe non-essential objects, but weaker than the soft reference object associated with a weak reference only survive until the next garbage collection before they occur. The next time garbage collection, regardless of whether sufficient memory, the recovery will be weak reference objects out of the association.

  • Virtual reference (Phantom Reference) also known as ghost or phantom cited references, it is a reference to the weakest. Whether an object has a virtual reference exists, will not have any impact on their survival time, can not be obtained by a phantom reference object instance. Set the virtual object reference purposes, the system is able to receive a notification when the object is recovered collector.

Reference counting algorithm

Determining whether the survival of the subject in many books such algorithms are: adding a reference counter, whenever a reference to its place, the counter value is incremented to a subject; when referring to the failure, the counter value is decreased by 1; any time counter to 0 the target is no longer in use.

Although the reference count of simple algorithm to determine the efficiency is high, but there is a downside, it is difficult to solve the problem of mutual circulation between object references. The following code, and objA objB refer to each other, if the reference counting method, the two reference objects are a counter value, the garbage collector can not cause recovery thereof.

/**
 * 引用记数算法测试
 * VM Args: -XX:+PrintGCDetails
 * Run With JDK 1.8
 * */
public class ReferenceCountingGC {

    public Object instance = null;
    private static final int _1M = 1024 * 1024;
    private byte[] bigSize = new byte[2 * _1M];

    public static void main(String[] args) {
        ReferenceCountingGC objA = new ReferenceCountingGC();
        ReferenceCountingGC objB = new ReferenceCountingGC();
        objA.instance = objB;
        objB.instance = objA;

        objA = null;
        objB = null;

        //这时发生GC,objA和objB能否被回收?
        System.gc();
    }
}

operation result:

[GC (System.gc()) [PSYoungGen: 7432K->728K(38400K)] 7432K->736K(125952K), 0.0012008 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 728K->0K(38400K)] [ParOldGen: 8K->667K(87552K)] 736K->667K(125952K), [Metaspace: 3491K->3491K(1056768K)], 0.0044445 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 PSYoungGen      total 38400K, used 333K [0x00000000d5c00000, 0x00000000d8680000, 0x0000000100000000)
  eden space 33280K, 1% used [0x00000000d5c00000,0x00000000d5c534a8,0x00000000d7c80000)
  from space 5120K, 0% used [0x00000000d7c80000,0x00000000d7c80000,0x00000000d8180000)
  to   space 5120K, 0% used [0x00000000d8180000,0x00000000d8180000,0x00000000d8680000)
 ParOldGen       total 87552K, used 667K [0x0000000081400000, 0x0000000086980000, 0x00000000d5c00000)
  object space 87552K, 0% used [0x0000000081400000,0x00000000814a6cf0,0x0000000086980000)
 Metaspace       used 3497K, capacity 4498K, committed 4864K, reserved 1056768K
  class space    used 387K, capacity 390K, committed 512K, reserved 1048576K

Looking at the results from the run, GC log contains "7432K-> 736K", meaning that the virtual machine does not refer to each other as the two objects do not recycle them, and whether virtual machines are not judged by reference counting algorithm live objects.

Reachability analysis algorithm

In mainstream programming language to achieve a lot in, it is by reachability analysis (Reachability Analysis) to determine whether the object alive. The basic idea of ​​this algorithm is: a series is referred to as "GC Roots" object as a starting point, to start the search downward from these nodes, called search path traversed reference chain (Reference Chain), when an object to GC Roots without any reference chain connected (in the words of graph theory is from GC Roots to this object is unreachable), then it proves that this object is not available.

As shown below, the object Object 5, Object 6, Object 7 although related to each other, but they are not up to the GC Roots, they are determined as recoverable objects:

image

In Java, can be used as an object GC Roots are the following:

  • Virtual Machine stack (Local Variable Table stack frame) in the object reference.
  • Method static property class object referenced area.
  • Object literal reference methods zone.
  • Native method stacks in the JNI (i.e., the general said method Native) object reference.

The object of self-salvation

Unreachable in reachability analysis algorithm is not a target "certain death", then they will be temporarily in a "probation" stage, to really pronounced dead, at least twice to go through the labeling process: the first time when the mark is carried out after reachability analysis found no references GC Roots connected to the chain, it is a marker; and then, if an object covers the finalize()method and has not yet been performed, the object will be placed in a call F-Queuequeue, there is a separate thread sequentially execution queue object's finalize()method, finalize()the method is the last chance the object of self-redemption, as long as the associated reference any object on the chain with GC Roots, you can cheat death, F-Queuethe queue object will be the second time mark. After two marks if the object has not escaped, that was basically it really recovered.

The following code is the object of a demonstration of self-redemption:

/**
 * 对象的一次自我救赎
 * 1. 对象可以在GC时自我救赎
 * 2. 这种机会只有一次,因为一个对象的finalize()方法至多会被调用一次
 * */
public class FinalizeEscapeGC {

    public static FinalizeEscapeGC SAVE_HOOK = null;

    public void isAlive(){
        System.out.println("yes, i am still alive");
    }

    @Override
    protected void finalize() throws Throwable{
        super.finalize();
        System.out.println("finalize method executed");
        //把自己赋值给类变量,即与GC Roots建立了关联
        FinalizeEscapeGC.SAVE_HOOK = this;
    }

    public static void main(String[] args) throws Throwable{
        SAVE_HOOK = new FinalizeEscapeGC();

        //对象第一次自我救赎
        SAVE_HOOK = null;
        System.gc();
        Thread.sleep(500);
        if(SAVE_HOOK != null) {
            SAVE_HOOK.isAlive();
        } else {
            System.out.println("no, i am dead");
        }

        //第二次自我救赎失败,因为finalize()只执行一次
        SAVE_HOOK = null;
        System.gc();
        Thread.sleep(500);
        if(SAVE_HOOK != null) {
            SAVE_HOOK.isAlive();
        } else {
            System.out.println("no, i am dead");
        }
    }
}

operation result:

finalize method executed
yes, i am still alive
no, i am dead

Seen from the operating results, SAVE_HOOKthe object of finalize()the method is indeed triggered the garbage collector, and managed to escape before being recycled. Code the same code two, the second time without success to escape, because an object finalize()method will only be called once the system automatically. In addition, the finalize()method of running a costly, large uncertainties, can not guarantee that the object of the calling sequence, so I do not recommend using this method, you can use try-finallyinstead.

Methods district

The method area there are garbage collection, but the garbage collection efficiency of this memory area is relatively low. In JDK1.6 Before and garbage collection method of recycling a major area of two parts: a constant and useless waste classes. But in JDK1.7 running time constants pool moved to the Java heap, the method area now largely recovered useless class. Often run basically the same amount of heap memory with the recovery method for recovering other objects.

Meet the following three conditions it will be determined as an unnecessary class:

  • All instances of the class have been recovered, which is the Java heap any instance of the class does not exist.
  • Load class ClassLoader has been recovered.
  • Java.lang.Class corresponding to the class object is not referenced in any place, not by the method of accessing the class reflected anywhere.

Virtual machines can be kind of useless meet the above three conditions of recovery, it is only "may" not necessarily be recovered. Whether the class is recovered, HotSpot virtual machine provides a -Xnoclassgcparameter control. In the use of a large number of reflective, dynamic proxies, etc. CGLib ByteCode frame, and dynamically generated JSP custom ClassLoader OSGi Such frequent scenario, the virtual machine needs to have the function of unloading classes, to ensure a method is not overflow.

Github Repo address article code: https://github.com/cellei/JVM-Practice

Guess you like

Origin www.cnblogs.com/cellei/p/12129798.html