Android memory leak detection with mat use

Source: Internet
Author: User
Tags message queue

basic concepts of memory leaks

Memory detection This part, related knowledge has the JVM virtual machine garbage collection mechanism, the class loading mechanism, the memory model and so on. Writing a program without a memory leak is important to improve the stability of the program and improve the user experience. Therefore, when learning Java to write programs using Java, pay special attention to memory leak related issues. Although the JVM provides an automatic garbage collection mechanism, there are still many situations that can cause a memory leak.
The main cause of a memory leak is a long-life object that holds a reference to an object with a short life cycle. This can cause short objects to be recycled at the time of the collection. Android is more typical: 1, static variables hold activity context. 2, or handler hold a component of the context, and if Looper message queue for the handler message is not processed, then will be held as target strong reference, resulting in the context can not be released, Causes the corresponding component to be unable to be reclaimed by memory when exiting. 3. The non-static inner class holds a reference to the external class by default, so that if we define a thread inner class in activity and run the thread directly from the new thread, the thread will hold a reference to the activity before the end of the run. This causes the activity to not be released.

Memory Detection ToolsLeakcananry

Leakcanary, the main monitoring is the use of activity,fragment components such as whether the memory is not recycled. The use of the method is also very simple, the equivalent of a listener, and then through normal operation to find a memory leak, a memory leak when there will be a toast, but also in the corresponding program to see where the memory leak occurred.
method is relatively simple, add leakcanary dependency, create a new application portal, install Leakcanary in OnCreate method.

When a memory leak occurs, a toast appears on the screen, opening the leaks program on the desktop, showing the leaked memory, such as:

The Leakcananry implementation steps are roughly:
The approximate steps to achieve are:
1. Automatically add activity to Keyedweakreference
2. In background thread, check if reference is cleared after OnDestroy, and no GC is triggered.
3, if the reference is not cleared, then dump heap to a hprof file and saved to the app file system
4. Start Heapanalyzerservice,heapanalyzer in a separate process use haha to analyze the heap dump.
5, Heapanalyzer in heap dump according to reference key to find keyedweakreference.
6, Heapanalyzer calculate the shortest strong reference path to GC roots to determine if there is a leak, and then build the reference chain that caused the leak.
7, the result is passed back to the app process Displayleakservice, and shows a leaked notification.
The method is a bit simple, but it can only detect the activity, fragment whether a memory leak occurs.

Watch overall memory usage

See the official documentation for details:
Https://developer.android.com/studio/profile/investigate-ram.html#ViewingAllocations
Using adb shell, go to mobile adb and execute commands:

<包名> [-参数]

You can view the memory allocations for different parts of your app. such as Java heap,native heap, etc.
The output is the current memory allocation for the specific application, in the unit kilobytes
Because the program involves JNI and often allocates local memory, the ADB shell is used to see how the native heap is allocated.

The results are as follows:

Analyze each parameter:
Private Clean/dirty RAM:
This part of the memory is the app's private memory, when the app is destroyed is the memory that the operating system can reclaim. The private dirty can only be used by your process, but only in memory, when the memory is not enough, and can not be stored by paging technology to the hard disk (operating system-related knowledge), Dalvik and native heap allocation are private dirty RAM. Named Dirty because it is the memory shared by the Dalvik heap and the native heap?

DDMS Use Process
    1. After you start eclipse, switch to the DDMS perspective and confirm that the devices view, the heap view, are open;
    2. Link the phone to the computer via USB, the link needs to confirm that the phone is in "USB debugging" mode, and not as "massstorage";
    3. After the link is successful, the serial number of the mobile device and the part of the process information that is running on the device will be displayed in the Devices view of the DDMS.
    4. Click to select the process you want to monitor, such as the system_process process;
    5. Click to select the "Update Heap" icon in the top row of icons in the Devices view interface;
    6. Click the "Cause GC" button in the heap view;
    7. In the heap view, you will see the details of the memory usage of the currently selected process.
How do I detect a memory leak?

In the middle of the heap view is a type called DataObject, the data object, which is the object instantiated in our program. In the data object row, there is a column "total size", whose value is the amount of memory for all Java data Objects in the current process, in general, the size of this value determines whether there is a memory leak.
Under normal circumstances, the total size value will be stable in a limited range, that is, no object is not garbage collection, so that although our continuous operation will continue to generate many objects, and in the process of the virtual machine continuous GC, these objects are recycled, Memory consumption will fall to a stable level. If there is a case where the object reference is not disposed in the code, then the total size value of DataObject will not come down significantly after each GC, and as the number of operations is increased, the value of total size becomes larger.

By means of DDMS, if the totalsize of DataObject is stable within a certain approximate range, it can be determined that no memory leaks have occurred.

MAT

However, not all memory leaks are obvious and will eventually result in Oom. Sometimes only a few objects are leaking, although the impact is not small, but undoubtedly wasted memory.
To find this more subtle memory leak, we need to use the Mat tool.
Before you understand the tree of domination, you should understand some of the relevant concepts.

Domination tree

The dominant tree embodies the dominant relationship between object instances, and in the object reference graph, all paths to object B pass through object A, which is considered object a dominates object B.

In this diagram, the left side is the object reference relationship, and for A and b, to reach both points must go through GC root. For C, you can also arrive from B from a, but all must go through GC root, so the closest dominating point is also GC root.
For Point D, whether from C->d or c->d->f->d, the closest point that must pass is C, so C is the dominant point of D. The same can be efhg in the dominant tree position.

Shallowheap and retained HEAP

The shallow heap represents the amount of memory the object itself occupies, and an object with a memory size of 100bytes shallow heap is 100bytes.
The retained heap means that by reclaiming the total amount of memory this object can reclaim, say a 100bytes object also directly or indirectly holds another 3 100bytes object reference, when the object is recycled if no other 3 objects can be recycled. The retained heap is 400bytes.
The data we often touch when using mat for analysis is shallow size and retained size:
Shallow Size
The size of the memory that the object occupies, excluding the objects it references.
For an object of a non-array type, its size is the sum of the size of the object and all its member variables. Of course, this will also include some Java language features of the data storage unit.
For an object of an array type, its size is the sum of the size of the array element object.
Retained Size
Retained size= the current object size + the sum of the size of the object to which the current object can be directly or indirectly referenced. (Meaning of indirect reference: A->b->c, C is indirect reference)
In other words, retained size is the amount of memory that the current object can be freed from the heap after it is GC.
However, when you release it, you also exclude objects that are referenced directly or indirectly by GC roots. They will not be recycled for the time being. Such as:

The shallow Size of the retained Size=a object of the A object
The retained of the B object is the shallow size of the shallow size + C object of the Size=b object.
Because the B object is freed, C is released at the same time, and D is not released because it is referenced directly by GC roots. The retained size is the amount of memory that can be freed from the heap after the current object has been GC.

These concepts are often used in memory analysis using mat, so keep in mind.

Download and use of mat

: https://eclipse.org/mat/downloads.php
There is no way to download the mat as an Eclipse plugin, but rather by downloading a separate software client.
First, select the process to detect in Ddms and dump HPROF file, such as:

A snapshot of the current memory is stored in hprof, so clicking the cause GC manually triggers a garbage collection before the dump snapshot, which avoids unnecessary objects such as soft references, weak references, and so on in memory that affect our analysis.

Dump the Hprof file, and use the SDK to carry out a format conversion, the tool in the SDK path under Platform-tools, the name is Hprof-conv.

How to use:
/.hprof-conv.exe a.hprof B.hprof
A is the input hprof file name and B is the output file name.
Then open the B.hprof in Eclipse Memory Analyzer, note that you want to convert the format, or you won't be able to open it successfully.
As follows:

Analyze memory leaks with mat

During the analysis, the main use is the histogram histogram, and the dominater tree.

Find the item with the largest retained heap value in the histogram view and analyze whether a memory leak occurs here.

Note that in general we ignore objects from Java and Android systems, and we focus on the objects in our own programs. So enter the filter class Name above.

The retained heap indicates how many objects cannot be reclaimed because of this object.

Right-click the corresponding class, list Objects->with incoming references. Indicates another class that references an instance of this class, that is, its parent node in the reference tree. Determine why the object was not garbage collected by analyzing who referred to it.
Outcoming reference is a child node that looks at some objects that are referenced by the current object.

Also see, Merge shortest path to GC root, you can find a shortest path to the GC root to see why the current object cannot be reclaimed.

Real-Combat analysis

The following records my specific analysis of a project, as well as the use of various tools.

1. Use DDMS to view memory

In the process of using DDMS, several tests were performed for the application, mainly to see the memory usage before the program runs and the memory usage after the program ran:
Before use:

After use:

Through the above data can be seen, before the program run data object is allocated on the heap is about 180KB, and the memory after the run about 300KB floating, did not present a significant rise in the situation, so there is no obvious memory leak, basically did not lead to the possibility of oom.

However, it can be found that the program runs once, placed a period of time, even if manually triggered GC, the memory on the heap, although back down, but still 288KB, and the 180KB before the execution of the large difference, indicating that some objects are GC roots reference, unable to complete the release.

Further analysis is performed using the Mat tool below. In the above process, three hprof files are transferred, and the Hprof files are formatted and converted using the tools under Android SDK tools for comparative analysis:

2. Analyze memory dumps using the mat

Previous analysis of memory use found that before and after use there is a difference of about 100KB, and even if placed for a period of time still cannot be used. Add the histogram of the before and after to the contrast bar and compare it in the mat:

Click on the red exclamation mark in the upper right corner:

The comparison found that the size of the two shallow heap is basically the same, the extra part is the Updatepartresultthread, the system class rather than our own programming caused by.
Take a look at the retained heap in the histogram before and after use:

As you can see, after the program executes, the Newactivity strongly references some objects, and retainedheap partial memory cannot be reclaimed until Newacitivity is released. This is the main reason we found the heap memory differences in DDMS.
Right-click the newactivity in the histogram to see the following options:

More are the list objects and merger shortest Paths to GC Roots.
List objects:
Outgoing reference is the child node of the current object in the dominant tree, which is what references the current object holds.
Incoming reference is the parent node, that is, who is referencing the current object and why it has not been recycled.

Merger shortest Paths to GC Roots: Find the shortest path to GC Roots for objects that are not currently being freed. That is, the current object is referenced by WHO, why is not released. This is because our object is an activity, and when it is displayed in the foreground, it is not garbage collected, so it is not the point of our analysis.

Here, we look at outgoing reference to see which strong references the current object has:

Exclude the object of the system, or the main analysis of the program we wrote.

Finally, when we used leakcanary, the registered listener was not recycled and a memory leak was found:).

Remove the leakcanary and test again to find that the value of the data object actually drops a lot.

Continuing the analysis, it was found that Newactivity quoted a

A portion of the memory could not be released. This problem is a client implementation problem and is not within the scope of a memory leak.
Next, filter out the service-side class in the histogram:

As you can see, most of the classes on the server shallow heap are 0, which is already garbage collected.

Conclusion

Conclusion
When using the mat to analyze memory, the most critical thing is to find a reference relationship. If an object that should be disposed of is not released, then we tend to look at its incoming reference to see who holds its strong references. Using the merger shortest GC roots to find the shortest path to GC root, it is determined that the GC is not possible because of whom it is referenced.

Android memory leak detection with mat use

Related Article

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.