Reference types in Java

Why are there so many middle reference types designed in the JDK?

First of all, Java is a language with its own GC, which means we don’t have to manage memory manually like C++ does. Java automatically cleans up unwanted objects, but then we have no control over the life cycle of objects.

There are a large number of objects in the system, with varying degrees of importance and life cycles. Therefore, we can use different reference types to control when the GC collects objects.

Objects can remain in memory when there is enough space; Memory space is still tight after garbage collection, and some objects can be discarded to free up memory.

After JDK 1.2, Java classifies reference objects into the following categories: the weaker the reference type from top to bottom:

  • Strong Reference
  • Soft Reference
  • Week Reference (weak Reference)
  • Phantom Reference

Java. Lang. Ref package structure:

ReferenceQueue

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        ReferenceQueue<Integer[]> queue = new ReferenceQueue<>();

        // Generate large objects so that GC cleans up the objects
        new Thread(() -> {
            HashMap<WeakReference<Integer[]>, Integer> map = new HashMap<>();
            for (int i = 0; i < 10000; i++) {
                map.put(new WeakReference<>(new Integer[1024 * 1024], queue), i);
            }
        }).start();

        // Monitor the cleaned object, at this point the object has been cleaned, only the WeakReference reference is left
        new Thread(() -> {
            Reference<? extends Integer[]> ref;
            while (true) {
                try {
                    while((ref = queue.remove()) ! =null) {
                        System.out.printf("Object reference: %s, object: %s\n", ref, ref.get()); }}catch(InterruptedException e) { e.printStackTrace(); } } }).start(); }}Copy the code

When the referenced object is cleared, the Reference(Week, Soft, Phantom) used to wrap the object is passed to the ReferenceQueue, which can then be retrieved from the queue for subsequent processing, such as determining whether a memory leak has occurred.

StrongReference

public class Main {
    public static void main(String[] args) {
        Object o = newObject(); }}Copy the code

When we create a new object using new, = is a strong reference, and GC will not clear the referenced object as long as the reference relationship exists.

SoftReference

import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;

public class Main {
    public static void main(String[] args) {
        ReferenceQueue<Object> refQ = new ReferenceQueue<>();
        Object o = new Object();
        // Create a soft reference to object o
        SoftReference<Object> refOne = new SoftReference<>(o);
        // Create a soft reference to object O and pass it to the ReferenceQueue, which will be passed to the queue when cleared
        SoftReference<Object> refTwo = newSoftReference<>(o, refQ); }}Copy the code

Soft references are used to describe objects that are useful, but not required.

All soft references to soft reachable objects are guaranteed to be cleared before the virtual machine throws an OutOfMemoryError.

As long as the reference to the soft reference is strongly reachable (the object has a strong reference chain at this time), that is, it is actually in use, the soft reference will not be purged.

import java.lang.ref.SoftReference;

public class Main {
    public static void main(String[] args) {
        Object o = new Object();
        SoftReference<Object> refOne = new SoftReference<>(o);
        // The object o has a strong reference and is therefore strongly reachableObject otherO = o; }}Copy the code

WeakReference

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;

public class Main {
    public static void main(String[] args) {
        ReferenceQueue<Object> refQ = new ReferenceQueue<>();

        Object o = new Object();
        WeakReference<Object> refOne = new WeakReference<>(o);
        WeakReference<Object> refTwo = newWeakReference<>(o, refQ); }}Copy the code

Weak references describe objects that are not required, but are weaker than SoftReference. Objects containing only weak reference chains will be purged during the next GC regardless of current memory availability.

PhantomReference

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        ReferenceQueue<Object> refQ = new ReferenceQueue<>();

        Object o = new Object();
        PhantomReference<Object> ref = new PhantomReference<>(o, refQ);

        The GC / / proposal
        o = null;
        System.gc();

        // Wait to get objects cleared by GC
        Reference<?> reference = refQ.remove();
        System.out.println(ref);
        System.out.println(reference);
    }
}

// answer
java.lang.ref.PhantomReference@59a6e353
java.lang.ref.PhantomReference@59a6e353
Copy the code

It can also be called phantom reference or phantom reference, the weakest kind of reference relationship.

The existence or absence of a virtual reference does not affect its life cycle and the object instance cannot be obtained.

The only function is to receive notification from the system when the object is cleared.

Four kinds of reference comparison

Reference types Remove time
StrongReference The strong reference relationship ends
SoftReference Memory is insufficient
WeakReference At the next GC
PhantomReference There is no