Review
A memory leak (memory leak) refers to a program failing to release memory that is no longer in use due to negligence or error. So in Android, when an object holds a reference to an activity, and if the object cannot be reclaimed by the system, the activity is not recycled by the system when the activity is no longer in use, so there is a memory leak. Two times in the application of memory leak acquisition will not have any impact, but after the application for a long time, if there is a large number of activity can not be collected by GC, will eventually lead to the emergence of oom. So we're here to analyze the common factors that lead to memory leaks and how to detect memory leaks.
Common factors that lead to memory leaks
Scenario One: Static activity and view
Static variables activity and view can cause memory leaks, and in this code the context and TextView of the activity are set to static objects, resulting in a memory leak.
Import Android.content.Context;
Import android.support.v7.app.AppCompatActivity;
Import Android.os.Bundle;
Import Android.widget.TextView;
public class Mainactivity extends appcompatactivity {
private static context;
private static TextView TextView;
@Override
protected void onCreate (Bundle savedinstancestate) {
super.oncreate (savedinstancestate);
Setcontentview (r.layout.activity_main);
context = this;
TextView = new TextView (this);
}
Scenario Two: Thread, anonymous class, inner class
There is a Non-static anonymous class object thread in the following code that implicitly holds the reference leakactivity of an external class, resulting in a memory leak. Similarly, if this thread is a leakactivity internal class rather than an anonymous inner class, he will also hold a reference to the external class and cause a memory leak. It is only necessary to define a static internal class for the thread anonymous class (the static inner class does not hold an implicit reference to the external class).
public class Leakactivity extends Appcompatactivity {
@Override
protected void OnCreate (Bundle Savedinstancestate) {
super.oncreate (savedinstancestate);
Setcontentview (r.layout.activity_leak);
Leakfun ();
}
private void Leakfun () {
new Thread (new Runnable () {
@Override public
void Run () {
try {
Thread.Sleep (Integer.max_value);
} catch (Interruptedexception e) {
e.printstacktrace ();}}}
);
}
Scenario Three: Animation
There is a class of infinite loop animation in the property animation, and if you play the animation in the activity and stop the animation in the OnDestroy, the animation will continue to play, and the activity will be held by the view, causing the activity to not be released. Solving such problems requires OnDestroy to call Objectanimator.cancel () in early activity to stop the animation.
public class Leakactivity extends Appcompatactivity {
private TextView TextView;
@Override
protected void onCreate (Bundle savedinstancestate) {
super.oncreate (savedinstancestate);
Setcontentview (r.layout.activity_leak);
TextView = (TextView) Findviewbyid (R.id.text_view);
Objectanimator objectanimator = objectanimator.offloat (TextView, "rotation", 0,360);
Objectanimator.setrepeatcount (valueanimator.infinite);
Objectanimator.start ();
}
Scenario Four: Handler
For handler memory leaks in (Android messaging mechanism--handler work process)
Scenario Five: Improper use of third party libraries
For the use of some of the third open source frameworks, such as Eventbus,rxjava, failure to unsubscribe before the activity is destroyed can lead to memory leaks.
Detecting memory leaks using mat
After introducing the common memory leaks, check out the memory leaks using mat (Memory analysis Tool). Mat's download address is: http://www.eclipse.org/mat/downloads.php.
Here's a look at an error code that could lead to a memory leak.
public class Leakactivity extends Appcompatactivity {
@Override
protected void OnCreate (Bundle Savedinstancestate) {
super.oncreate (savedinstancestate);
Setcontentview (r.layout.activity_leak);
Eventbus.getdefault (). Register (this);
@Subscribe public
void Subscriber (String s) {
}
}
There is a memory leak in the above code because Eventbus is not unregistered. Let's take this code as an example to see how to analyze a memory leak.
Open the monitors in Androidstudio to see the following interface.
Here you can see that when the application just started, the memory occupied by 15M, and then we now start to operate the app, repeatedly entered the exit leakacticity. Click the GC button on the top. This time we are looking at memory usage.
Here we can see that the memory has been increasing continuously, has reached 33M, and cannot be reclaimed by GC. So we can judge that there is a memory leak in this case. Now click on the Dump Java heap button to see the generated hprof file in the captures window. However, the generated hprof file is not in the standard format and we need to transform it through the tools provided by the SDK, which is in the Platform-tools directory of the SDK. The following commands are executed:
Hprof-conv xxx.hprof Converted-dump.hprof
Of course in the Androidstudio can omit this step, you can directly export the standard format of the Hprof file.
You can then use the Mat tool to open the exported hprof file. Open the interface as shown in the following illustration:
The most commonly used in mat is the histogram and Dominator tree, which correspond to the A and B buttons in the above picture respectively. Histogram can see the number of different types of buffer in memory and the size of memory consumed, while Dominator tree sorts objects in memory in order from large to small, and can analyze referential relationships between objects. Here again to introduce the meaning of two symbols in mat.
- Shallowheap: The amount of memory occupied by the object itself, excluding the objects he refers to
- Retainedheap: The amount of memory consumed by the object itself, plus its direct or indirect reference to the object's size
Histogram
Because most of the common memory leaks in Android appear in Acivity, you can click on the Histogram button and search for activity.
It can be seen here that there are 69 objects in the leakactivity, which can basically determine the existence of a memory leak, which can be analyzed by looking at the reference chain of the GC object. Click the right mouse button to select the merge shortest paths to GC roots and select exclude Weak/soft references to exclude weak references and soft references.
After you exclude soft references and weak references, the following illustration shows:
Here you can see the leakactivity memory leak caused by Eventbus.
You can also see in histogram that an object contains references to those objects. For example, now to see the references contained in leakactivity, you can click the right mouse button to select the With incoming reference in the list objects. The With Outcoming reference indicates that the selected object holds references to those objects.
Here to write a picture description
Dominator Tree
Now click here to click the Dominator Tree button and search for activity. You can see the following illustration:
Here you can see that there are a lot of leakactivity. Then click the right mouse button to select path to GC roots->exclude Weak/soft references to exclude weak references and soft references.
You can then see the following result, which is still a memory leak caused by Eventbus:
Summarize
Memory leaks are often overlooked by us, but when a large amount of memory leaks leads to oom. Its impact is also not to be underestimated. Of course, in addition to the above memory leak analysis, we can also use Leakcanary to analyze the memory leak. The use of leakcanary is not detailed here.
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.