There are four JVM reference levels

If an object has a reference to it, then the object will not be collected by GC? — No limitations

Object obj = new Object() ; – strong reference

According to the relationship between strong and weak references: Strong reference > Soft reference > Weak reference > virtual reference

Strong reference

Object obj = new Object() ;

Convention: reference obj, reference Object New Object()

What invalidates a strong reference object?

1. End of life cycle (scope failure)

public void method(){ Object obj = new Object() ; }// When the method completes, the strong reference to the reference and the Object new Object() are waiting to be collected by the GCCopy the code

2. The reference is set to NULL and the reference object is collected by GC

obj = null ; // At this point, there are no references to the new Object(), so the new Object() waits to be collected by the GCCopy the code

In all but two cases, the GC does not reclaim strongly referenced objects.

Soft references

Depending on JVM memory: If there is enough memory, GC will not randomly reclaim soft reference objects; If the JVM runs out of memory, the GC proactively reclaims soft reference objects.

Various sources of citation:

Strong reference: new

Soft Reference Weak Reference Virtual Reference: Reference

Soft references: Java lang. Ref. SoftReference

Reference has a get() method that returns the referenced object

SoftReference<SoftObject> softRef = new SoftReference<>(new SoftObject() );
Copy the code

Softref.get () –> returns the SoftObject object to which the reference points

package ref; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.List; Class SoftObject{} public class SoftReferenceDemo {public static void main(String[] args) throws Exception { SoftRef -->SoftObject In design mode: SoftReference<SoftObject> softRef = new SoftReference<>(new SoftObject()); List<byte[]> list = new ArrayList<>(); // Start a thread, New Thread(()->{while(true) {if (softref.get () == null) // Soft reference object {system.out.println (" Soft reference object has been recycled..") ); System.exit(0); }}}," thread A").start(); While (true){// thread.sleep (10); if(softRef.get() ! = null) list.add(new byte[1024*1024]) ; // Add 1m content to list at a time}}}Copy the code

A weak reference

Timing of collection: Weak reference objects are collected as soon as GC is executed.

java.lang.ref.WeakReference

package ref; import java.lang.ref.WeakReference; public class WeakReferenceDemo { public static void main(String[] args) throws Exception { WeakReference<Object> weakRef  = new WeakReference<>(new Object()); //weakRef->Object System.out.println( weakRef.get()==null ? "Recycled ":" not recycled"); System.gc(); Thread.sleep(100); System.out.println( weakRef.get()==null ? "Recycled ":" not recycled"); }}Copy the code

Virtual reference (phantom or phantom reference)

java.lang.ref.PhantomReference

Whether a virtual reference is used has nothing to do with the reference object itself. The object itself cannot be obtained by a virtual reference.

Reference get() -> reference object

Virtual references get() -> null

Phantom reference not used alone, general meeting and reference queue (Java. Lang. Ref. ReferenceQueue) are used together.

Value: When the GC collects an object, if the GC finds that the object still has a virtual reference, it places the virtual reference in the reference queue, and then (when the virtual reference is out of the queue) reclaims the object. Therefore, we can use the virtual reference + reference object implementation: do some additional operations before the object is gc.

GC -> If there are virtual references -> virtual references in queue -> virtual references out of queue -> Reclaim object

package ref; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; class MyObject { } public class PhantomReferenceDemo { public static void main(String[] args) throws Exception { MyObject obj = new MyObject(); ReferenceQueue queue = new ReferenceQueue(); PhantomReference<MyObject> phantomRef = new PhantomReference<>(obj, queue); // let the GC perform a collection operation obj = null; System.gc(); Thread.sleep(30); System. Out.println (" GC to perform..." ); / / GC - > virtual reference - > team - > the team - > obj System. Out. The println (queue. The poll ()); }}Copy the code

Special case: If a virtual reference object overrides Finalize (), then the JVM delays the enqueueing of a virtual reference.

package ref; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; class MyObject3 { @Override protected void finalize() throws Throwable { super.finalize(); System.out.println(" Before being recycled...") ); } } public class PhantomReferenceDemo2 { public static void main(String[] args) throws Exception { MyObject3 obj = new MyObject3(); ReferenceQueue queue = new ReferenceQueue(); PhantomReference<MyObject3> phantomRef = new PhantomReference<>(obj, queue); // let the GC perform a collection operation obj = null; System.gc(); // Thread.sleep(30); System. Out.println (" GC to perform..." ); / / GC - > virtual reference - > team - > the team - > obj System. Out. The println (queue. The poll ()); // Virtual references are not enqueued system.gc (); // Thread.sleep(30); System. Out.println (" GC to perform..." ); / / GC - > virtual reference - > team - > the team - > obj System. Out. The println (queue. The poll ()); // Virtual references are delayed until the second gc to be enqueued system.gc (); // Thread.sleep(30); System. Out.println (" GC to perform..." ); / / GC - > virtual reference - > team - > the team - > obj System. Out. The println (queue. The poll ()); System.gc(); Thread.sleep(30); System. Out.println (" GC to perform..." ); / / GC - > virtual reference - > team - > the team - > obj System. Out. The println (queue. The poll ()); }}Copy the code

Final Class Finalizer extends FinalReference: Final reference

Constructor () -> destructor (). In Java, finalizers can automatically reclaim unwanted objects, so there is no need to write destructors.

One thing the JVM can manipulate directly: indirect memory

Direct memory: native (operating system memory, not JVM memory)

Finalizer will reclaim direct memory that the JVM can’t manipulate and that it forgot to close.