Android performance optimization: Using MAT to Analyze memory leakage, androidmat

Source: Internet
Author: User

Android performance optimization: Using MAT to Analyze memory leakage, androidmat

Reprinted please indicate this article from xiaanming blog (http://blog.csdn.net/xiaanming/article/details/42396507), please respect others' hard work results, thank you!

When developing Android applications, we may accidentally generate OOM. Although JAVA has a garbage collector, we cannot prevent memory leaks or memory overflow. as technology advances, the memory size of mobile devices is getting bigger and bigger, but due to the uneven Android devices, it may be good to run on this device, and OOM will be reported when running on that device. These adaptation problems are also quite painful, for example, we usually run an application and it runs well. Suddenly an OOM error occurs to you in an Activity. You may think this Activity causes memory leakage, is it possible that the memory is leaked? Memory leakage is like a time bomb, which may crash our application at any time. Therefore, as an Android developer, we still need the ability to analyze Memory leakage, here we should talk about memory leakage. Memory leakage refers to a reference pointing to an object that is no longer in use, so that the object will not be recycled by the garbage collector. Therefore, the garbage collector cannot recycle objects with memory leaks. This article uses the DDMS (Dalvik Debug Monitor Server) and MAT (Memory Analyzer Tool) tools to analyze Memory leakage issues.


Prepare the tool

DDMS is a debugging tool provided by ADT. For more information about how to use DDMS, see dig.


How to detect memory leakage

1. Use DDMS to detect memory leakage

Open the Devices view, select the application process to be analyzed, and click the Updata Heap button.


Then, open the DDMS, select the Heap tag, click the Cause GC button, and click the Cause GC to manually trigger the JAVA garbage collector, as shown in figure


If we want to test whether memory leakage of an Activity occurs, we can repeatedly enter and exit the Activity, and then manually trigger several garbage collection times, observe whether the Size of the Total Size in the data object column is stable or there is a major change trend. If there is a major change trend, it indicates that the Activity has a memory leakage problem, we need to analyze it in detail.


2. Use Logcat to detect memory leakage

When the Garbage Collector recycles the garbage, it will make the relative output in Logcat, so we can also determine whether there is a memory leakage problem through this information.

1. There are four types of GC causes for the first part of the message above.
GC_CONCURRENT: when your heap memory is quickly used up, this GC recycle will be triggered.
The memory of the GC_FOR_MALLOC heap is full and new memory needs to be allocated.
GC_EXTERNAL_ALLOC is generated before Android3.0 (Honeycomb) when external Memory is released (for example, Bitmap objects generated before 2.3 are stored in Native Memory. This type of memory allocation is no longer available in Android3.0 and later versions.
GC_EXPLICIT is generated when System. gc is called. Click the Cause GC button to manually trigger the log information generated by the garbage collector.

2. freed 1413K indicates that GC has released 1434K memory

3. 20% free 9349 K/11644 K, 20% indicates the percentage of currently allocable memory, 9349K indicates the memory occupied by the current active object, and 11644 K indicates the Heap size

4. paused 8 ms + 3 ms, total 71 ms indicates the GC application suspension time and the total GC consumption time.

With this log information, we can know whether the GC has successfully released some memory after several times of running. If the allocated memory continuously increases, the memory leakage obviously exists, the following is the Log information of Memory leakage:

Obviously, the percentage of idle memory in Heap to total Heap is decreasing, and the percentage of active objects in Heap is increasing.


Memory leakage analysis

The following is an example of code with Memory leakage. This is also a common method of Memory leakage. It is to write some internal classes in the Activity, in addition, these internal classes have a long life cycle.

Package com. example. memoryleak; import java. util. arrayList; import java. util. list; import android. app. activity; import android. OS. bundle; public class LeakActivity extends Activity {private List <String> list = new ArrayList <String> (); @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); // simulate some other objects of Activity for (int I = 0; I <10000; I ++) {list. add ("Memory Leak! ");} // Enable the thread new MyThread (). start ();} public class MyThread extends Thread {@ Overridepublic void run () {super. run (); // simulate time-consuming operations try {Thread. sleep (10x60*1000);} catch (InterruptedException e) {e. printStackTrace ();}}}}
Run the sample code, select the Devices view, click the Updata Heap tag above, then rotate the screen, repeat several times, and then click Dump HPROF file, the Eclipse MAT plug-in will automatically open for us, as shown in figure


The following Histogram (Histogram) lists the statistics of each object. The Dominator Tree provides the arrangement of the most memory-occupied objects in the program, these two are the most used for troubleshooting memory leaks.

Histogram (Histogram)

Let's take a look at Histogram, one of MAT's most useful tools, which can list the number of instances of any class. It supports regular expressions to find a specific class, and can also calculate the minimum or exact value of all objects in this class. We can input LeakActivity through regular expressions, histogram lists the LeakActivity-related classes.


We can see that LeakActivity and MyThread internal classes both have 16 objects, although LeakActivity and MyThread have so many objects, however, this does not allow us to accurately determine whether the two objects have memory leaks. Select com. example. memoryleak. right-click LeakActivity, as shown in figure


Merge Shortest Paths to GC Roots can check whether an object is connected to RC Roots by reference link. in JAVA, the Reachability Analysis is used to determine whether the object is alive, the basic idea of this algorithm is to use a series of objects named "GC Roots" as the starting point and start searching down from these nodes. The paths searched are called reference chains, when an object is not linked to GC Roots, the object is regarded as an object that can be recycled. Otherwise, the object cannot be recycled. We can select exclude all phantom/weak/soft etc. references (check for virtual references, weak references, soft references, etc.) Because objects that are referenced by virtual references, weak references, and soft references can be directly recycled by GC.


We can see that LeakActivity has a GC Roots chain, that is, there is a memory leakage problem. We can see that LeakActivity is held by this $0 of MyThread.

In addition to using Merge Shortest Paths to GC Roots, we can also use

List object-With outgoing References: displays the objects held by the selected object.

List object-With incoming References show that the selected object is held by those external objects

Show object by class-With outgoing References: displays the objects held by the selected object. These objects are sorted by class combination.

Show object by class-With incoming References: displays the external objects holding the selected object. These objects are sorted by class combination.


Dominator Tree)

It sorts all objects by Heap size. The usage is similar to Histogram (Histogram). I will not introduce it too much here.


We know that in the above example code, we know that the internal class will hold external class references. If the internal class's lifecycle is too long, it will cause external class memory leakage, then you will ask, what should we do to avoid Memory leakage? Since the internal class does not work, we can use the external class or static internal class. If we need to use something in the external class, we can pass the Weak Reference of the external class

Package com. example. memoryleak; import java. lang. ref. weakReference; import java. util. arrayList; import java. util. list; import android. app. activity; import android. OS. bundle; public class LeakActivity extends Activity {private List <String> list = new ArrayList <String> (); @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); // simulate some other objects of the Activity for (int I = 0; I <10000; I ++) {List. add ("Memory Leak! ");} // Enable the thread new MyThread (this ). start () ;}public static class MyThread extends Thread {private WeakReference <LeakActivity> mLeakActivityRef; public MyThread (LeakActivity) {mLeakActivityRef = new WeakReference <LeakActivity> (activity );} @ Overridepublic void run () {super. run (); // simulate time-consuming operations try {Thread. sleep (10x60*1000);} catch (InterruptedException e) {e. printStackTrace ();} // if you want to use LeakActivity, add LeakActivity = mLeakActivityRef. get (); if (activity! = Null) {// do something }}}}

Similarly, Handler has the same problem, for example, the following code

package com.example.memoryleak;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;public class LeakActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);MyHandler handler = new MyHandler();handler.sendMessageDelayed(Message.obtain(), 10 * 60 * 1000);}public class MyHandler extends Handler{@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);}}}
We know that when using MyHandler to send a Message, the Message will be added to the MessageQueue of the main thread, and the target of each Message will hold the MyHandler object, this $0 of MyHandler will hold the LeakActivity object, so when we rotate the screen, the LeakActivity leakage will inevitably be caused because every Message is delayed for 10 minutes, so we need to modify the code.

package com.example.memoryleak;import java.lang.ref.WeakReference;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;public class LeakActivity extends Activity {MyHandler handler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);handler = new MyHandler(this);handler.sendMessageDelayed(Message.obtain(), 10 * 60 * 1000);}public static class MyHandler extends Handler{public WeakReference<LeakActivity> mLeakActivityRef;public MyHandler(LeakActivity leakActivity) {mLeakActivityRef = new WeakReference<LeakActivity>(leakActivity);}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if(mLeakActivityRef.get() != null){//do something}}}@Overrideprotected void onDestroy() {handler.removeCallbacksAndMessages(null);super.onDestroy();}}

The above Code ensures that LeakActivity will not be leaked. Note that handler. removeCallbacksAndMessages (NullIn this way, the target MyHandler of each Message will be released when LeakActivity exits. Therefore, when using a non-static internal class, pay attention to whether the life cycle of the internal class is longer than that of the external class. If so, we can use the above solution.


Common Memory leakage problems

1. the above two cases

2. The resource object is not closed, such as the Cursor and IO operations in database operations.

3. After the registerReceiver is called to register the broadcast, the unregisterReceiver () is not called to cancel the registration.

4. View. getViewTreeObserver (). addOnXXXListener is called, but View. getViewTreeObserver (). removeXXXListener is not called.

5. Before Android 3.0, there is no call recycle () for Bitmap that is not in use, of course, after Android 3.0 does not need, for more details, please view the http://blog.csdn.net/xiaanming/article/details/41084843

6. Contenx leakage. For example, we use the Context object in the singleton class, as shown below:

import android.content.Context;public class Singleton {private Context context;private static Singleton mSingleton;private Singleton(Context context){this.context = context;}public static Singleton getInstance(Context context){if(mSingleton == null){synchronized (Singleton.class) {if(mSingleton == null){mSingleton = new Singleton(context);}}}return mSingleton;}}

Assume that Singleton is used in an Activity. getInstance (this) or this instance will cause the Activity to be referenced by the Singleton object all the time. Therefore, we should use getApplicationContext () to replace the Context of the Activity, getApplicationContext () the obtained Context is a global object, so Memory leakage is avoided. Similarly, setting the Context Member to static may cause memory leakage.

7. do not override the finalize () method. Sometimes we may release some resources before an object is recycled. It may be done in the finalize () method, but the finalize object is implemented, the process of creation and recovery is more time-consuming. An additional Finalizer object is created to point to the newly created object. During garbage collection, at least two GC operations are required. The first GC detects that the object is only referenced by Finalizer and put the object into Finalizer. referenceQueue at this time, because of the reference of Finalizer, the object cannot be GC,
Finalizer $ FinalizerThread will constantly clean up the Queue object, remove the current element, and execute the finalize method of the object. After the object is cleared, there is no reference to it, and the next GC will be recycled, therefore, the object remains alive for a longer time, resulting in Memory leakage.

If you still have some memory leaks, please submit them. I will update them!


The blogger participated in the CSDN 2014 blog Star Selection. I hope you will be free to vote for it. Thank you!

Http://vote.blog.csdn.net/blogstar2014/details? Username = xiaanming # content








Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.