Android Studio and Mat used in conjunction to analyze memory issues

Source: Internet
Author: User

Memory leaks are frequently encountered in Android development, and the Android system has a certain memory limit for individual apps, which can be obtained by:

ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);int memoryClass = am.getMemoryClass();

The Momeryclass value in the above code can be used as the memory limit for each app. This value is different depending on the device manufacturer, for example, my simulator value is 32M, if an app running on my simulator, allocating more than 32M of memory space, will be reported oom (memory overflow)! Memory leaks are also a potential cause of memory overflow, so you must have a way to resolve memory overflows.

This chapter focuses on using Android studio to see if there is a memory leak problem, and then uses the mat (memory Analyzer Tool) to analyze and resolve the memory leak problem.

Android Studio analyzes if there is a memory leak

Opening the memory panel in Android Monitor in Android Studio, you can see a graph of the heap memory with a real-time change, as shown in

The highlights of the 3 sections include:

    1. Tested terminal Setup, I did the test on the simulator nexus_s
    2. The process being tested, click to select another application or process
    3. Memory allocation in the currently tested process
      • Allocated represents the allocated space
      • Free stands for available remaining space
      • Allocated + Free cannot exceed app memory limit (32M)
    4. The Memory Analysis toolbar, from top to bottom, has a total of 4 buttons, followed by:
      Stop detection switch, no real effect

      is to manually invoke the GC, we must manually click the Initiate GC button to manually trigger the GC before grasping the memory, so that the captured memory usage does not include the Unreachable object (unreachable refers to objects that can be reclaimed by the garbage collector. But because there is no GC, so there is no release, then the memory used in the capture of the unreachable is these objects)

      Get hprof file (hprof file is the file we use when we use the Mat tool to analyze memory), but the file mat directly generated here is not directly available and needs to be converted into a standard hprof file. can be converted using Androidstudio or HPROF-CONV command, online can be found

      Start distribution tracking, first click to specify where to start tracking memory, and the second click to end the tracking location. So we intercept a section of memory to be analyzed, wait a few seconds Androidstudio will open a allocation view for us (feel the same as the Mat tool, but the mat tool is more powerful, we can also get the Hprof file, using mat to analyze)


Write a code to dynamically demonstrate:

The XML layout file follows, defines a button, and sets the OnClick property

<?xml version= "1.0" encoding= "Utf-8"?><LinearLayoutXmlns:android= "http://schemas.android.com/apk/res/android" android: Layout_width= "match_parent" android:layout_height= "match_parent" android:orientation= " Vertical "> <button android: Text= "Test memory Monitor" android:onclick=  "click" android:layout_width= " Wrap_content "android:layout_height=" wrap_content "/>< Span class= "Hljs-tag" ></LINEARLAYOUT>       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

The activity code is as follows: Declares the click Method of the button hit callback

public void click(View view) {        for (int i = 0; i < 10000; i++) { ImageView imageView = new ImageView(this); list.add(imageView); }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

With the above code, it is foreseen that each time a button is clicked, 10,000 ImageView are dynamically generated and added to the list to be saved, memory is as follows:

As you can see, the system has just started allocating about 2M of memory, and when you click on a button, the memory increases to 8 m, and the memory is increased to about 24M.
In this case, when we press back to exit activity and then click on the Init GC button to perform the garbage collection operation, the memory in the process will go back to 2M, such as:

In this case, the code is safe and stable code, but what if there is a memory leak in the activity, then let's modify the previous code to think of constructing a memory leak scenario, as shown in the following code:

PublicClassMainactivityExtendsappcompatactivity {Private list<imageview> List =New Arraylist<> ();Static Memoryleak Memoryleak;@OverrideProtectedvoid oncreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); if (memoryleak = null) {memoryleak = new memoryleak ();} } public void click (view view) { Span class= "Hljs-keyword" >for (int i = 0; i < 10000; i++) {ImageView ImageView = new ImageView (this); List.add ( ImageView); }} class Memoryleak {void dosomething () {System.out.println ( " WHEEE!!! ")}}                
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

As you can see, in mainactivity, a non-static memory class Memoryleak is added, and a static memoryleak reference is declared.
Run the above code, and then perform the click button again, you can see the memory will also rise to about 8M, click to rise to about 16M again, but after the return button is pressed and the garbage collection operation, allocated + Free total space has not been back to about 2M, But has been hovering around 8M to indicate the existence of memory leaks!!! But why would it be 8M??

Android studio generates memory byte files

Just now when I introduced the memory panel of studio, I mentioned a toolbar dump Java Heap, which can be exported by clicking this button to export a hprof file, this process will be slow, you need to wait patiently, when the center circle stops turning, the Hprof file is exported successfully.

This file will open automatically when the export is complete, as shown in:

Click the green run arrow on the right side of the analyzer tasks, and Android Studio will automatically analyze which classes have memory leaks based on this hprof file, as shown in:

There was a memory leak in the mainactivity, but it was a bit different from what I had expected, and I thought to a lot of people on the web that there was a memory leak every time a mainactivity was opened, but now the facts are in front of us. It dawned on me that Memoryleak was declared static in the first mainactivity, when the second opened Mainactivity would not reinitialize the Memoryleak object again, so the static The Memoryleak object is simply a reference to the object that holds the first mainactivity in memory, so when we invoke multiple GC operations, only the first mainactivity is actually not recycled by GC!!

If you change the code of the activity
Package material.danny_jiang.com.adbmemoryanalyze;Import Android.app.ActivityManager;Import Android.content.Context;Import android.support.v7.app.AppCompatActivity;Import Android.os.Bundle;Import Android.util.Log;Import Android.view.View;Import Android.widget.ImageView;Import java.util.ArrayList;Import java.util.List;PublicClassMainactivityExtendsappcompatactivity {Private list<imageview> List =New Arraylist<> ();private static Memoryleak Memoryleak;@OverrideProtectedvoidOnCreate (Bundle savedinstancestate) {Super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main);Memoryleak = new Memoryleak (); }PublicvoidClick (View view) {for (int i =0; i < 10000; i++) {ImageView ImageView = new ImageView (this); List.add (ImageView);} new Thread () { @Override  Public void run () {super.run (); Span class= "Hljs-keyword" >while (true) {try { System.out.println ( "Thread running!!"); Thread.Sleep (300);} catch (interruptedexception e) {e.printstacktrace ();}} }}.start (); } class Memoryleak {void dosomething () {System.out.println (               
      1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • Ten
    • one
    • 2
    • (
    • )
    • +
    • +
    • /
    • 0
    • +
    • all
    • +
    • +
    • +
    • -
    • 29
    • +
    • +
    • all
    • +
    • +
    • PNS
    • up
    • i>39
    • 48
    • all
    • /
    • /
    • /
    • /li>
    • ,
    • ,
    • ,
    • up-
    • -
    • +
    • -
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21st
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

As you can see, the scene that caused the memory leak was changed from the inner class to the internal thread class, and the log was printed indefinitely in the thread.

Execute again Enter mainactivity– return key – operation to enter mainactivity– return key

Then generate the Hprof file and open it, and perform analyzer Tasks to see information such as the slice:

You can see that every mainactivity you open will cause a memory leak. Wipe it!! Why is this happening now??? This is a problem with threads in Java-one feature of thread in Java is that they are directly referenced by GC root, which means that the Dalvik virtual machine holds strong references to all activated threads, causing the GC to never reclaim these thread objects Unless the thread is manually stopped and set to null or the user directly killed the process operation. See this believe you should also have the answer in mind: I have created a thread in each mainactivity, this thread will hold the mainactivity reference, even if the current thread exits the activity because it is directly referenced by GC root so it will not be recycled. Causes Mainactivity to be recycled by GC as well. So when using a thread, be sure to consider stopping the thread and releasing it in time when the activity exits

Mat Memory Analysis Tool

Normally, it's enough to use studio to analyze a simple memory leak based on what I've said above, but there's a more powerful memory analysis tool Mat before studio, which Google engineers call more powerful!! . Now let's look at how to use the mat to analyze memory problems

1 First download the Mat tool on the Eclipse website

https://www.eclipse.org/mat/

2 after downloading the mat and installing it, you need to be a hprof file.

These two I still use the front of the case to cause memory leaks to demonstrate,

    • First time you open mainactivity, click the dump heap to generate a hprof file
    • followed by a series of operations, such as Click button, press the Back button, again into the mainactivity and so on, here I repeat 4 times as above, and then click on the dump heap generated hprof file
3 Click the captures bar in studio to display the Hprof file you just generated, as shown in:


These two files we need to use the mat to open and contrast analysis, but Mat can not directly open the two files, you need to convert it to the mat can recognize the file, captures bar, right click on each hprof file, and then select Export to Standard. Hprof and save to the computer directory, such as:

4 Use the mat to open the converted Hprof file, showing as


You can see a panel with two dumps, each of which shows a pie chart of memory. One of the most used features is the lower left corner of the histogram, click the actions under the histogram item will get histogram results:

It is listed by class name for all instance objects and can be sorted by clicking on the header of the table, and a regular expression can be entered in the first row of the table to match the result:

In histogram, you can right-click on an object you want to view, and then select list objects to see all instances of this object, such as

When selected, jumps out of all instance object panels, where you can continue a specific instance of path to GC Root in memory (a strong reference starting from the GC). In the previous case operation, I repeatedly entered MainActivity4 times, and then clicked button to run the thread, so normally mainactivity should have 4 instances in memory, such as

Exclude all phantom/weak/soft means that all virtual references/soft references/weak references are excluded because only strong references can cause memory leaks! To display the message after clicking:

As you can see, mainactivity is eventually called Mainactivity.1OfRightLikeCitedUse,andMAINAc ti< Span id= "mathjax-span-33" class= "Mi" style= "font-family:stixgeneral; Font-style:italic ">v ity 1 is the anonymous inner class thread object created in the click Method. Finally, we found the root cause of the memory leak: When the activity exits, thread is referenced directly by GC root, so it will not be recycled by GC, and the thread and the activity reference cause the activity to not be collected properly by GC. caused the activity of memory leak, done!!!

How to discover memory leaks

The previous methods for analyzing memory using Android Studio and Mat are described separately. Android Studio's own memory analysis tool is intuitive and convenient, but its functionality is not as powerful as the mat, especially when there is no effective search and sorting capabilities. Faced with some tricky problems, you might want to use the mat to analyze memory.

The example above is that we artificially created a memory leak and then intentionally tested it with a tool. But how do we find out about memory leaks in real-world development? I think you can first use the heap analysis tool in studio or DDMS to observe that when you repeatedly perform an action (such as opening a page, clicking a button, loading a resource, and so on), memory remains near a stable value after the GC is executed. If memory is on a linear growth trend, there must be a memory leak. At this point, dump out the memory image and use the tool to analyze it.

When analyzing memory, the first is to use the tool's own leak checker to help locate. In addition, you can dump a memory image before and after the operation (suspected of causing a memory leak), and then use Mat's compare basket to compare the memory of two files, which helps to locate which object has been compromised. Then find this object's GC Roots, so that you can further locate the specific code.

Summary of common memory leak issues

Please check the link: http://blog.csdn.net/zxm317122667/article/details/52106741

Android Studio and Mat used in conjunction to analyze memory issues

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.