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.