Ali interview review: what are the four Java references and what are their differences?

We all know that in JVM garbage collection, GC can judge whether the object instance or data in the heap is garbage by reference counting method and reachability algorithm.

Whether the number of references of an object is determined by the reference counting algorithm, whether the reference chain of an object is reachable by the root search algorithm, and whether the object survives are related to "reference".

quote

Let's talk about references, references in Java, which are similar to pointers in C language. When we first learned Java, we knew that Java data types are divided into two categories: basic types and reference types.

Basic type: the smallest granularity data type built into the programming language. It includes four categories and eight types:

  • Four integer types: byte, short, int, long
  • There are two types of floating point numbers: float and double
  • 1 character type: char
  • 1 boolean type: Boolean

Reference type: the reference type refers to an object, not the original value, and the variable pointing to the object is a reference variable. In Java, in addition to basic types, other types belong to reference types, which mainly include classes, interfaces, arrays, enumerations and annotations

With data types, the management of program data by JVM is standardized. Different data types have different storage forms and locations

How to deviate, return to the subject, and operate the objects in the heap through reference. Quoting a passage from Java programming ideas,

”Each programming language has its own way of data processing. Sometimes programmers have to pay attention to what type of data they are going to process. Do you manipulate elements directly or use some indirect representation based on special syntax (such as pointers in C/C + +) to manipulate objects. All this is simplified in Java, and everything is treated as an object. Therefore, we can adopt a unified grammar. Although everything is "treated" as an object, the manipulated identifier is actually a "reference" to an object

For example:

Person person = new Person("Zhang San");
Copy code

The Person here is a reference to the Person instance "Zhang San". We generally operate the "Zhang San" instance through Person.

Before JDK 1.2, the definition of reference in Java was very traditional: if the value stored in the data of reference type represents the starting address of another block of memory, the reference data is called a reference representing a block of memory and an object. This definition is pure, but too narrow. Under this definition, an object has only two states of being referenced or not being referenced. There is nothing to do about how to describe some objects that are "tasteless to eat and regrettable to abandon".

For example, we want to describe such an object: when the memory space is enough, it can be retained in memory; If you are still very nervous after garbage collection, you can discard these objects. The caching functions of many systems meet such application scenarios.

After JDK 1.2, Java has extended the concept of reference and divided reference into

  • Strong Reference
  • Soft Reference
  • Weak Reference
  • Phantom Reference

The four citation intensities gradually weaken in turn.

The purpose of introducing four kinds of references in Java is to let the program decide the object life cycle. The JVM handles these four kinds of references differently through the garbage collector to change the object life cycle.

UML diagram in JDK 8

[picture upload failed... (image-6b10b-1633994688)]

The FinalReference class is visible in the package. The other three reference types are public and can be used directly in the application.

Strong reference

The most common in Java is strong reference. Assigning an object to a reference variable is a strong reference. References like "Object obj = new Object()".

When an object is referenced by a strongly referenced variable, it is reachable and cannot be recycled by the garbage collector, even if the object will never be used.

When the memory is insufficient, the JVM starts garbage collection. For strongly referenced objects, * * even if there is an OOM, the object will not be recycled and will not be collected** Therefore, strong references are sometimes one of the reasons for Java memory leaks.

For an ordinary object, if there is no other reference relationship, it is generally considered that it can be recycled by the garbage collector as long as it exceeds the scope of the reference or explicitly assigns the corresponding (strong) reference to null. (the specific recycling time depends on the garbage collection strategy).

coding~

public class StrongRefenenceDemo {

    public static void main(String[] args) {
        Object o1 = new Object();
        Object o2 = o1;
        o1 = null;
        System.gc();
        System.out.println(o1);  //null
        System.out.println(o2);  //java.lang.Object@2503dbd3
    }
}
Copy code

Although o1 has been recycled in the demo, o2 strongly refers to o1 and always exists, so it will not be recycled by GC

Soft reference

Soft reference is a relatively strong reference that weakens some references. It needs to be implemented with the java.lang.ref.SoftReference class to exempt objects from some garbage collection.

Soft references are used to describe objects that are useful but not necessary. For objects associated with soft references, these objects will be listed in the recycling range and recycled for the second time before the memory overflow exception will occur in the system. If there is still not enough memory for this recovery, a memory overflow exception will be thrown.

For objects with only soft references: when the system memory is sufficient, it will not be recycled, and when the system memory is insufficient, it will be recycled.

coding~

//VM options: -Xms5m -Xmx5m
public class SoftRefenenceDemo {

    public static void main(String[] args) {
        softRefMemoryEnough();
        System.out.println("------Insufficient memory------");
        softRefMemoryNotEnough();
    }

    private static void softRefMemoryEnough() {
        Object o1 = new Object();
        SoftReference<Object> s1 = new SoftReference<Object>(o1);
        System.out.println(o1);
        System.out.println(s1.get());

        o1 = null;
        System.gc();

        System.out.println(o1);
        System.out.println(s1.get());
    }

     /**
     * JVM Configure ` - Xms5m -Xmx5m ', and then deliberately new a large object to generate OOM due to insufficient memory. See the recovery of soft references
     */
    private static void softRefMemoryNotEnough() {
        Object o1 = new Object();
        SoftReference<Object> s1 = new SoftReference<Object>(o1);
        System.out.println(o1);
        System.out.println(s1.get());

        o1 = null;

        byte[] bytes = new byte[10 * 1024 * 1024];

        System.out.println(o1);
        System.out.println(s1.get());
    }
}
Copy code

Output

java.lang.Object@2503dbd3
java.lang.Object@2503dbd3
null
java.lang.Object@2503dbd3
------Insufficient memory------
java.lang.Object@4b67cf4d
java.lang.Object@4b67cf4d
java.lang.OutOfMemoryError: Java heap space
	at reference.SoftRefenenceDemo.softRefMemoryNotEnough(SoftRefenenceDemo.java:42)
	at reference.SoftRefenenceDemo.main(SoftRefenenceDemo.java:15)
null
null
 Copy code

Soft references are usually used in memory sensitive programs. For example, the cache is useful for soft references, which are retained when the memory is enough, and recycled when it is not enough.

Let's take a look at the soft references used by the Mybatis cache class SoftCache

public Object getObject(Object key) {
    Object result = null;
    SoftReference<Object> softReference = (SoftReference)this.delegate.getObject(key);
    if (softReference != null) {
        result = softReference.get();
        if (result == null) {
            this.delegate.removeObject(key);
        } else {
            synchronized(this.hardLinksToAvoidGarbageCollection) {
                this.hardLinksToAvoidGarbageCollection.addFirst(result);
                if (this.hardLinksToAvoidGarbageCollection.size() > this.numberOfHardLinks) {
                    this.hardLinksToAvoidGarbageCollection.removeLast();
                }
            }
        }
    }
    return result;
}
Copy code

Weak reference

Weak references are also used to describe non essential objects, but their strength is weaker than soft references. Objects associated with weak references can only survive until the next garbage collection. When the garbage collector works, objects associated with only weak references will be recycled regardless of whether the current memory is sufficient or not.

Weak references need to be implemented with the java.lang.ref.WeakReference class, which has a shorter lifetime than soft references.

For objects with only weak references, as soon as the garbage collection mechanism runs, the memory occupied by the object will be reclaimed regardless of whether the memory space of the JVM is sufficient.

coding~

public class WeakReferenceDemo {

    public static void main(String[] args) {
        Object o1 = new Object();
        WeakReference<Object> w1 = new WeakReference<Object>(o1);

        System.out.println(o1);
        System.out.println(w1.get());

        o1 = null;
        System.gc();

        System.out.println(o1);
        System.out.println(w1.get());
    }
}
Copy code

Weak reference objects, which do not prevent their referents from being made finalizable, finalized, and then reclaimed. Weak references are most often used to implement canonicalizing mappings.

According to the official document, weak references are often used to implement normalized mapping. The WeakHashMap in JDK is an example

Interviewer: since you all know weak references, can you talk about WeakHashMap

public class WeakHashMapDemo {

    public static void main(String[] args) throws InterruptedException {
        myHashMap();
        myWeakHashMap();
    }

    public static void myHashMap() {
        HashMap<String, String> map = new HashMap<String, String>();
        String key = new String("k1");
        String value = "v1";
        map.put(key, value);
        System.out.println(map);

        key = null;
        System.gc();

        System.out.println(map);
    }

    public static void myWeakHashMap() throws InterruptedException {
        WeakHashMap<String, String> map = new WeakHashMap<String, String>();
        //String key = "weak";
        // Just started writing the code above
        //Think about it. What if you write it like that? That's not a quote
        String key = new String("weak");
        String value = "map";
        map.put(key, value);
        System.out.println(map);
        //Remove strong references
        key = null;
        System.gc();
        Thread.sleep(1000);
        System.out.println(map);
    }
}
Copy code

Let's look at the weak references used in ThreadLocal

static class ThreadLocalMap {

    static class Entry extends WeakReference<ThreadLocal<?>> {
        Object value;

        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
    //......
}
Copy code

Virtual reference

Virtual reference is also called "ghost reference" or "phantom reference", which is the weakest reference relationship.

Virtual reference, as the name suggests, is a virtual reference, which is different from other references. Whether an object has a virtual reference will not affect its lifetime, nor can it be used to obtain an object instance through virtual reference.

Virtual reference needs to be implemented by java.lang.ref.phantom reference.

If an object only holds virtual references, it may be recycled by the garbage collector at any time just like it does not have any references. It cannot be used alone or access objects through it. Virtual references must be used in conjunction with the ReferenceQueue.

The main function of virtual reference is to track the status of object garbage collection. It only provides a mechanism to ensure that the object does something after it is finalize d.

The get method of phantom reference always returns null, so the corresponding reference object cannot be accessed. The significance is that an object has entered the finalization stage and can be recycled by GC to realize more flexible recycling operations than the finalization mechanism.

In other words, the only purpose of setting a virtual reference is to receive a system notification or add further processing when the object is recycled by the collector.

Java allows you to use the finalize() method to do the necessary cleanup before the garbage collector clears the object from memory.

public class PhantomReferenceDemo {

    public static void main(String[] args) throws InterruptedException {
        Object o1 = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
        PhantomReference<Object> phantomReference = new PhantomReference<Object>(o1,referenceQueue);

        System.out.println(o1);
        System.out.println(referenceQueue.poll());
        System.out.println(phantomReference.get());

        o1 = null;
        System.gc();
        Thread.sleep(3000);

        System.out.println(o1);
        System.out.println(referenceQueue.poll()); //Reference queue
        System.out.println(phantomReference.get());
    }

}
Copy code
java.lang.Object@4554617c
null
null
null
java.lang.ref.PhantomReference@74a14482
null
 Copy code

Reference queue

ReferenceQueue is used to work with reference. It can run without ReferenceQueue.

SoftReference, WeakReference and phantom reference all have a constructor that can pass ReferenceQueue.

When creating a reference, you can specify the associated queue. When GC releases the object memory, it will add the reference 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, which is equivalent to a notification mechanism.

When there is data in the associated reference queue, it means that the object in the heap memory pointed to is recycled. In this way, the JVM allows us to do what we want to do after the object is destroyed.

####Space is limited. More about the differences between the four citations can be found at https://www.bilibili.com/video/BV1pq4y1d79u/ Watch the more detailed explanation.

If you think you can gain something, you can praise and collect attention. Next, I will continue to analyze and share the relevant knowledge of Android, and you can continue to pay attention. If you really want to learn Android development or work in this field, I will share it with you for free. Of course, I hope everyone can support me more. Your praise is my motivation, thank you!

Keywords: Java C# Android Design Pattern Interview

Added by Morbius on Tue, 12 Oct 2021 02:53:47 +0300