All subclasses of Reference have the following characteristics: 1. A Reference subclass cannot be created directly without parameters, and must at least take strong Reference objects as construction parameters to create their own subclass objects; 2. Create objects with strong Reference objects as construction parameters, so that the objects in heap memory pointed to by the original strong Reference will not only be directly associated with the strong Reference itself, but also have certain connection with the Reference of the subclass object of Reference. And this connection may affect the object’s garbage collection.
Strong reference – Strong reference
One of the most common reference types in actual coding. A A = new A();
The strong reference itself is stored in stack memory, which points to the address of the object in memory. Typically, when there is no longer any strong reference to an object in memory, the garbage collection machine starts to think about possible garbage collection of that memory. For example, when encoding: a = null, at this point, the newly created a object in the heap has no other reference, when the system garbage collection, the heap memory will be garbage collected.
Soft Reference – Soft Reference
A SoftReference object is created using a strong reference to the object, and srA in stack memory points to the object.
import java.lang.ref.SoftReference;
public class ReferenceTest {
public static void main(String[] args) {
A a = new A();
SoftReference<A> srA = new SoftReference<A>(a);
a = null;
if (srA.get() == null) {
System.out.println("Object A enters garbage collection process");
} else {
System.out.println("Object A has not been reclaimed" + srA.get());
}
// Garbage collection
System.gc();
if (srA.get() == null) {
System.out.println("Object A enters garbage collection process");
} else {
System.out.println("Object A has not been reclaimed"+ srA.get()); }}}class A {}Copy the code
Output result:
A Object has not been reclaimed A@4807ccf6 A object has not been reclaimed A@4807ccf6Copy the code
When a = null, there will no longer be any strong references to an OBJECT in the heap, but there will be srA references to objects that point to a. When this indicator object is returned the first time the sra.get () method is called, get() has a result because the garbage collector has most likely not already done garbage collection. When the program executes system.gc (); After the garbage collection is forced, the indicated object A is still available through sra.get (), indicating that the object A has not been garbage collected.
An object indicated by a soft reference needs to meet the following two conditions to start being garbage collected: \
1. When the object it indicates does not have any strong reference object to it; 2. If the VM memory is insufficient. \
Therefore, SoftReference prolongs the amount of time that the object is specified to occupy the heap until the garbage collector reclaims the heap when the VM is out of memory.
Weak Reference – Weak Reference
import java.lang.ref.WeakReference; public class ReferenceTest { public static void main(String[] args) { A a = new A(); WeakReference<A> wrA = new WeakReference<A>(a); a = null; If (wra.get () == null) {system.out.println ("a object enters the garbage collection process "); } else {system.out.println ("a object has not been reclaimed "+ wra.get ()); } // Garbage collection system.gc (); If (wra.get () == null) {system.out.println ("a object enters the garbage collection process "); } else {system.out.println ("a object has not been reclaimed "+ wra.get ()); } } } class A { }Copy the code
Output result:
Object A has not been collected A@52e5376a Object A enters the garbage collection processCopy the code
When garbage collection is complete, wra.get () returns null, indicating that the indicator object is in garbage collection. WeakReference does not change the garbage collection time of the original strong reference object. Once it indicates that the object does not have any strong reference object, the object enters the normal garbage collection process.
The main usage scenarios are as follows: Currently there is a strong reference pointing to a strong reference object, at this time, due to business needs, it is necessary to increase the reference to this object, and at the same time, it is not expected to change the garbage collection time of this reference. At this time, WeakReference just meets the demand, which is common in some life-cycle scenarios.
public class MainActivity extends AppCompatActivity { private int page; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 1) { page++; }}}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new Runnable() { @Override public void run() { Message msg = Message.obtain(); msg.what = 1; handler.sendMessage(msg); } }).start(); }}Copy the code
You will see the following warning message:
This Handler class should be static or leaks might occur (anonymous android.os.Handler) less… (Ctrl+F1)
Inspection info:Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected. If the Handler is using a Looper or MessageQueue for a thread other than the main thread, then there is no issue. If the Handler is using the Looper or MessageQueue of the main thread, you need to fix your Handler declaration, as follows: Declare the Handler as a static class; In the outer class, instantiate a WeakReference to the outer class and pass this object to your Handler when you instantiate the Handler; Make all references to members of the outer class using the WeakReference object. Issue id: HandlerLeak
When you use a Handler in an Activity, you need to define it as a static inner class so that it can be decoupled from the external class and no longer hold references to the external class. At the same time, because the handlerMessage in Handler generally needs to access or modify the attribute of the Activity more or less, at this point, WeakReference pointing to the Activity needs to be defined in the Handler so that it will not affect the Activity’s memory reclamation. You can access the Activity’s properties under normal conditions.
import java.lang.ref.WeakReference;
public class MainActivity extends AppCompatActivity {
private int page;
private MyHandler mMyHandler = new MyHandler(this);
private static class MyHandler extends Handler {
private WeakReference<MainActivity> wrActivity;
public MyHandler(MainActivity activity) {
this.wrActivity = new WeakReference<MainActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
if (wrActivity.get() == null) {
return;
}
MainActivity mActivity = wrActivity.get();
if (msg.what == 1) { mActivity.page++; }}}@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run(a) {
Message msg = Message.obtain();
msg.what = 1; mMyHandler.sendMessage(msg); } }).start(); }}Copy the code
For SoftReference and WeakReference, there is also a constructor parameter named ReferenceQueue. When the object indicated by SoftReference or WeakReference is indeed garbage collected, The reference will be placed in the ReferenceQueue. Note that in the above, when the get() method of SoftReference or WeakReference returns NULL, it only indicates that the object indicated has entered the garbage collection process, and the object may not be garbage collected. A reference will only be placed in the ReferenceQueue if it is confirmed to be garbage collected.
import java.lang.ref.WeakReference;
public class ReferenceTest {
public static void main(String[] args) {
A a = new A();
WeakReference<A> wrA = new WeakReference<A>(a);
a = null;
if (wrA.get() == null) {
System.out.println("Object A enters garbage collection process");
} else {
System.out.println("Object A has not been reclaimed" + wrA.get());
}
// Garbage collection
System.gc();
if (wrA.get() == null) {
System.out.println("Object A enters garbage collection process");
} else {
System.out.println("Object A has not been reclaimed"+ wrA.get()); }}}class A {
@Override
protected void finalize(a) throws Throwable {
super.finalize();
System.out.println("in A finalize"); }}Copy the code
Output: Validates the statement “entering the garbage collection process” above.
A object has not been collected A@46993aaa a object enters garbage collection process ina FinalizeCopy the code
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
public class ReferenceTest {
public static void main(String[] args) {
A a = new A();
ReferenceQueue<A> rq = new ReferenceQueue<A>();
WeakReference<A> wrA = new WeakReference<A>(a, rq);
a = null;
if (wrA.get() == null) {
System.out.println("Object A enters garbage collection process");
} else {
System.out.println("Object A has not been reclaimed" + wrA.get());
}
System.out.println("rq item:" + rq.poll());
// Garbage collection
System.gc();
if (wrA.get() == null) {
System.out.println("Object A enters garbage collection process");
} else {
System.out.println("Object A has not been reclaimed" + wrA.get());
}
System.out.println("rq item:"+ rq.poll()); }}class A {
@Override
protected void finalize(a) throws Throwable {
super.finalize();
System.out.println("in A finalize"); }}Copy the code
Result: Verify that SoftReference or WeakReference reference that only enters the garbage collection process is not added to the ReferenceQueue.
A object is not collected A@302b2c81 RQ item: NULL A object enters the garbage collection process Rq item:null ina FinalizeCopy the code
import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; public class ReferenceTest { public static void main(String[] args) { A a = new A(); ReferenceQueue<A> rq = new ReferenceQueue<A>(); WeakReference<A> wrA = new WeakReference<A>(a, rq); a = null; If (wra.get () == null) {system.out.println ("a object enters the garbage collection process "); } else {system.out.println ("a object has not been reclaimed "+ wra.get ()); } System.out.println("rq item:" + rq.poll()); // Garbage collection system.gc (); If (wra.get () == null) {system.out.println ("a object enters the garbage collection process "); } else {system.out.println ("a object has not been reclaimed "+ wra.get ()); } try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("rq item:" + rq.poll()); } } class A { @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("in A finalize"); }}Copy the code
Output result:
A object has not yet been recycling a @ 6276 e1db rq item: null objects into a recycling process in a finalize rq item: Java lang. Ref. WeakReference @ 645064 fCopy the code
Virtual reference – PhantomReference
Compared with SoftReference or WeakReference, PhantomReference has the following main differences: Refertomreference (T referent, ReferenceQueue
q), therefore, PhantomReference must be used in conjunction with ReferenceQueue; 2. PhantomReference’s get() method returns null regardless of whether there is a strong reference to the pointer to PhantomReference.
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class ReferenceTest {
public static void main(String[] args) {
A a = new A();
ReferenceQueue<A> rq = new ReferenceQueue<A>();
PhantomReference<A> prA = new PhantomReference<A>(a, rq);
System.out.println("prA.get():" + prA.get());
a = null;
System.gc();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("rq item:"+ rq.poll()); }}class A {}Copy the code
Output result:
prA.get():null
rq item:java.lang.ref.PhantomReference@1da12fc0
Copy the code
Thread.sleep(1); Ensure that the garbage collection thread can execute. Otherwise, virtual references that enter the garbage collection process without actually being garbage collected will not be added to PhantomReference.
Like WeakReference, PhantomReference does not change the garbage collection timing of its indicated object. ReferenceQueue role is mainly used to monitor SoftReference WeakReference/PhantomReference indicates whether the object is garbage collection.
Reference: Android has four types of references: strong reference, soft reference, weak reference, and virtual reference