There are four types of references in java/android, respectively:
Strong reference-strong reference
Soft Reference-Soft reference
Weak Reference-Weak reference
Phantom Reference-Virtual reference
Different reference types have different characteristics, and they also correspond to different usage scenarios.
1.Strong Reference-strong reference
One of the most common reference types in the actual encoding. Common forms such as: a A = new A (); The strong reference itself is stored in stack memory, and it stores points to the address of an object in memory. In general, the garbage collection machine begins to consider a possible garbage collection for this memory when there is no longer any strong reference to the object in memory to point to it. For example, when encoding: a = null, at which point the address is just assigned in the heap and the new a object has no other references, heap memory is garbage collected when the system is garbage collected.
SoftReference, WeakReference, phantomreference are subclasses of class java.lang.ref.Reference. Reference, as an abstract base class, defines the basic operations of its subclass objects. The reference subclass has the following characteristics:
1.Reference subclasses cannot be directly created without any parameters, and must create their own subclass objects at least with strong reference objects as construction arguments;
2. Because the object is created in the 1 with a strong reference object for the construction parameter, the object in the heap memory that the original strong reference points to is no longer only directly associated with the strong reference itself, but also with reference to the reference of the subclass object. This connection may affect garbage collection for the object.
Three subclasses, namely SoftReference, WeakReference, and Phantomreference, are formed according to the different effects of garbage collection on objects that are indicated by different subclass objects (strong references to objects in the heap memory).
2.Soft Reference-Soft reference
Soft references are generally used in the following forms:
A A = new A ();
softreference<a> SrA = new softreference<a> (A);
A SoftReference object is created with the strong reference of the object as a parameter, and the WRA in the stack memory is pointed to this object.
At this point, the following encoding is made: a = null, what effect does it have on the garbage collection of a object that was originally pointed to by a?
Just look at the output of the following program:
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 ("A object enters garbage collection process");
} else {
System.out.println ("A object has not been reclaimed" + Sra.get ());
}
Garbage collection
System.GC ();
if (sra.get () = = null) {
System.out.println ("A object enters garbage collection process");
} else {
System.out.println ("A object has not been reclaimed" + Sra.get ());
}} Class A {
}
# #输出结果为:
1 A object has not been reclaimed A@4807ccf6
2 A object has not been reclaimed a@4807ccf6
When a = null, a object in heap memory will no longer have any strong references to it, but there is still a SRA reference object pointing to a object. This is well understood when the first call to the Sra.get () method returns this indicator object, because the garbage collector is likely to have not been garbage collected, at which point the get () is a result. When the program executes System.GC (), after the garbage collection is forced, the Sra.get () is found to still be able to obtain the indicated a object, stating that object A is not garbage collected. So, when does the object indicated by the soft reference start to be garbage collected? The following two conditions need to be met:
1. When the object to which it indicates does not have any strong reference object pointing to it;
2. When the virtual machine is low on memory.
As a result, the SoftReference in disguise prolongs the amount of time it indicates that the object occupies the heap, and the garbage collector reclaims the heap memory space until the virtual machine is low on memory.
3.Weak Reference-Weak reference
Similarly, soft references are generally used in the following forms:
A A = new A ();
weakreference<a> WrA = new weakreference<a> (A);
What are the characteristics of garbage collection when no strong reference is directed to this object?
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 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 garbage collection process");
} else {
System.out.println ("A object has not been reclaimed" + Wra.get ());
}} Class A {
}
# #输出结果为:
A object has not been reclaimed a@52e5376a
a object into the garbage collection process
The first result of the output is explained in the same way. When garbage collection is made, Wra.get () returns null indicating that the object has entered the garbage collection process. Therefore, the characteristics of weak references are summarized as follows:
WeakReference does not change the time of the garbage collection of the original strongly referenced object, which enters the normal garbage collection process once it indicates that the object does not have any strong reference objects.
So, according to this feature, there may be doubt: what is the significance of weakreference existence?
The main use scenario is that a strong reference to a strongly referenced object is currently present, and the reference to this object needs to be increased as a result of the business needs, without the need to change the timing of the garbage collection of this reference, where WeakReference meets the requirements and is common in some life cycle scenarios.
Here's an Android scenario for weakreference use--combining static internal classes and WeakReference to address possible handler memory leaks in an activity.
In the activity we need to create a new thread to get the data and use the Handler-sendmessage method. The following is a general code for this process:
public class Mainactivity extends activity {
//...
private int page;
Private Handler Handler = new Handler () {
@Override public
void Handlemessage (msg) {
if (Msg.what = 1 ) {
//...
page++;
} else {
//...
}
}; @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;
Msg.obj = XX;
Handler.sendmessage (msg);
}
}). Start ();
//...
}
}
Run Link in Eclispe will see a warning message: This Handler class should to be static or leaks might occur ... Click here to view this information and explain the problem in its details and give a suggested solution.
Issue:ensures that Handler classes does not hold in to a reference to a outer class
Id:handlerleak
Since this Han Dler is declared as a inner class, it may prevent the outer class from being garbage. If the Handler is using a looper or MessageQueue to thread other than the main thread, then there is no issue. If the Handler is using the Looper or MessageQueue's main thread, you are need to fix your Handler, as declaration S:declare the Handler as a static class;in the outer class, instantiate a weakreference to the "outer class and pass" object to your Handler if you instantiate the Handler; Make all references the outer class using the WeakReference object.
The idea is to define handler as an internal static class, and to define a weakreference reference in this static inner class, because it indicates an external activity object.
Problem Analysis:
The activity has its own lifecycle, during which a newly opened thread in the activity is running, possibly when the user presses the back key, or if the system is low on memory, and so on, Since the new thread in the activity does not follow the cycle of the activity itself, that is, when the activity executes the OnDestroy, due to the thread and the presence of the handler handlemessage, This will not be possible because the system would have expected this activity to be garbage collected, because implicitly holding references to external classes in the non-static inner class could cause memory leaks.
Therefore, when using handler in an activity, one needs to define it as a static internal class form, so that it can be decoupled from the external class (activity) and no longer hold the reference to the external class. At the same time, because the handlermessage in handler generally will need to access or modify the properties of the activity, it is necessary to define the weakreference that points to the activity within handler. So that it does not affect the memory recycle of the activity, it is possible to access the properties of the activity under normal circumstances.
Google's official advice is:
public class Mainactivity extends activity {//... 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 (msg) {if (wractivity.get () = null) {return;
} mainactivity mactivity = Wractivity.get ();
if (msg.what = = 1) {//... mactivity.page++;
} else {//...}
} @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;
Msg.obj = XX; Mmyhandler.sendmessage (msg);
}). Start ();
//...
} }
For SoftReference and WeakReference, there is also a constructor parameter of Referencequeue<t>, and when the object indicated by SoftReference or weakreference is indeed garbage collected, Its references will be placed in Referencequeue. Note that when the SoftReference or WeakReference get () method returns NULL, the object is not necessarily garbage collected until the object indicated it has entered the garbage collection process. And only after the confirmation is garbage collected, if referencequeue, its reference will be placed in the referencequeue.
Look at one of the following examples:
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 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 garbage collection process");
} else {
System.out.println ("A object has not been reclaimed" + Wra.get ());
}} Class A {
@Override
protected void Finalize () throws Throwable {
super.finalize ();
System.out.println ("In A Finalize");
}
# #输出结果为:
1 A object has not been recycled A@46993AAA
2 A object is recycled
3 in a finalize
From this, it also validates the above "into the garbage collection process" argument. The following combination of Referencequeue, look at a piece of code:
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 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 garbage collection process");
else {System.out.println ("A object has not been reclaimed" + wra.get ());
}/* Try {thread.sleep (1000);
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"); }
}
# #输出结果为:
A object has not been reclaimed a@302b2c81
RQ Item:null
A object into the garbage collection process
RQ item:null in
A finalize
This verifies that the SoftReference or WeakReference references that enter the garbage collection process have not been added to the referencequeue.
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 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 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");
}
# #输出结果为:
Object A has not been reclaimed a@6276e1db
RQ Item:null
A object into the garbage collection process in
A finalize
RQ item:java.lang.ref.weakreference@ 645064f
Thus, the above statement is confirmed.
4.PhantomReference
Compared with softreference or weakreference, the major differences in phantomreference are reflected in the following points:
1.PhantomReference only one constructor phantomreference (T referent, referencequeue<? super T> Q), therefore, Phantomreference use must be combined with referencequeue;
2. The phantomreference Get () method returns a null result, regardless of whether there is a strong reference to the indicated object pointing to Phantomreference.
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 {
}
# #输出结果为:
Pra.get (): null
RQ ITEM:JAVA.LANG.REF.PHANTOMREFERENCE@1DA12FC0
The Thread.Sleep (1) in the code, as in the previous example, ensures that the garbage collection thread can execute. Otherwise, a virtual reference to an object that is entered into the garbage collection process without actually being garbage collected is not added to the phantomreference.
As with WeakReference, Phantomreference does not change the timing of garbage collection for its indicated object. And can be summed up: the role of referencequeue is mainly used to monitor the Softreference/weakreference/phantomreference whether the object has been garbage collection.
The above is a small series for everyone to bring the Java/android reference type and its use of comprehensive analysis of all the content, hope to help everyone, a lot of support cloud Habitat Community ~