Android Memory leak debug

Source: Internet
Author: User

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Copyright NOTICE: This article for the brother even original article, without the Bo Master permission not reproduced.

Android Memory Leak Debug
I. Overview
If we write code that has too much memory usage, it will inevitably make our device run slowly, or even crash. To enable Android apps to run safely and quickly, each Android application uses a proprietary Dalvik virtual machine instance to run, with each application running in its own process. On the one hand, if a memory leak occurs during the process of running the program, it will only make its own
The process is killed without affecting other processes (which can cause a system restart if a system process such as system_process is causing problems). On the other hand, Android allocates different memory usage caps for different types of processes, and if the application process uses more memory than this limit, it is considered a memory leak by the system and is killed.

The upper memory limit that Android allocates for the app process is as follows:
Location:/android_source/system/core/rootdir/init.rc section Script

```# Define The Oom_adj values for the classes of processes so can be killed by the kernel.# These is used in Activitymanagerservice.setprop ro. Foreground_app_adj0setprop ro. Visible_app_adj1setprop ro. Secondary_server_adj2setprop ro. Backup_app_adj2setprop ro. Home_app_adj4setprop ro. Hidden_app_min_adj7setprop ro. Content_provider_adj14setprop ro. Empty_app_adj15# Define the memory thresholds at which the above process classes willbe killed.# These numbers is in pages (4k). SetProp ro. Foreground_app_mem1536setprop ro. Visible_app_mem2048setprop ro. Secondary_server_mem4096setprop ro. Backup_app_mem4096setprop ro. Home_app_mem4096setprop ro. Hidden_app_mem5120setprop ro. Content_provider_mem5632setprop ro. Empty_app_mem6144# Write value must is consistent with the above properties.# Note that the driver only supports 6 slots and so we had home_app at the same memory level Asservices.write/sys/module/lowmemorykiller/parameters/adj 0, 1,2,7, 14,15write/proc/sys/vm/overcommit_memory 1WRITE/PROC/SYS/VM /min_free_order_shift 4write/sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096, 5120,5632,6144# Set init its Forked children ' s Oom_adj.write/proc/1/oom_adj-16   
    • 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
    • 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

Second, the common memory improper use of the situation

(i) the query database did not close the cursor
Describe:
The process of querying the database is often done, but there are often cases where the Cursor is not closed after it has been used.
If our query result set is relatively small, the memory consumption is not easy to be found, only in the case of a large number of operations in a regular time
Will reproduce the memory problem, which will bring difficulties and risks to future testing and troubleshooting.

Example code:

...);if (cursor.moveToNext()) {... ...}
    • 1
    • 2
    • 1
    • 2

To fix the sample code:

Cursor cursor = null;try {cursor = getContentResolver().query(uri ...);if (cursor != null && cursor.moveToNext()) {... ...}}finally {if (cursor != null) {try {cursor.close();}catch (Exception e) {} }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

(ii) When constructing Adapter, no cached Convertview is used
Describe:
To construct the baseadapter of the ListView as an example, the method is improved in Baseadapter:
public view GetView (int position, view Convertview, ViewGroup parent) gives the ListView the View object that is required for each item. Initially, the ListView instantiates a certain number of view objects from the Baseadapter based on the current screen layout, and the ListView caches the View objects.
When you scroll up the ListView, the View object that was originally on top of the ListItem is recycled and then used to construct the newly-appearing list item. This construction process is done by the GetView () method, and the second parameter view convertview of GetView () is the view object of the cached list item (the cache does not have a view object when it is initialized CONVERTVI EW is null). It can be seen that if we do not use Convertview, but each time in the GetView () to re-instantiate a View object, that is, wasting resources is also a waste of time, it will also make memory consumption more and more. The ListView process for recovering ListItem view objects can view the:android.widget.abslistview.java–> void Addscrapview (View scrap) method.

Example code:

public View getView(int position, View convertView, ViewGroup parent) {View view = new Xxx(...); ... ...return view;}
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

To fix the sample code:

public View getView(int position, View convertView, ViewGroup parent) {View view = null;if (convertView != null) { view = convertView; populate(view, getItem(position)); ...}else { view = new Xxx(...); ...}return view;}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

(iii) Bitmap object does not call recycle () to free memory when it is in use
Describe:
Sometimes we will manipulate the Bitmap object manually, if a Bitmap object compares the memory, when it is not being used
, you can call the Bitmap.recycle () method to reclaim the memory occupied by the pixels of this object, but this is not a must
, depending on the circumstances.
You can look at the comments in the code:

/* Free upThe memory associatedWith this bitmap ' s pixels,and MarkThe * bitmapas  "dead", meaning it would throw an Exception if getpixels () or * setPixels () is called, and willdraw nothing. This operation cannot is * reversed, so it should only be called if You are sure Thereare no further uses for the bitmap. This is a advanced call, and normally need * not be called,since the normal GC process would Free up this memory when * There is no morereferences to this bitmap. */   /span>             
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

(iv) Releasing a reference to an object
Describe:
Give two examples to illustrate.
Example A:
Suppose you have the following actions

public class DemoActivity extends Activity {... ...private Handler mHandler = ... private Object obj;public void operation() {obj = initObj(); ...mHandler.post(new Runnable() {public void run() {useObj(obj);}});}}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

We have a member variable, obj, in operation () we want to be able to post the operation that handles the obj instance to the
The MessageQueue of a thread. In the above code, even if the thread where the Mhandler is running out
Object referenced by obj

, but this object is still not garbage collected, because Demoactivity.obj still retains the reference to this object. The

If the object is no longer used in the demoactivity, you can release the object at the location of [Mark]

Cited

And the code can be modified to: ...

public void operation() {obj = initObj(); ...final Object o = obj;obj = null;mHandler.post(new Runnable() {public void run() {useObj(o);} }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

Example B:
Assuming that we want to listen to the telephony service in the system in the lock screen (lockscreen) to get some information (such as signal strength, etc.), you can define a Phonestatelistener object in Lockscreen and register it with the Telephonyma The Nager service. For Lockscreen objects, when the lock screen needs to be displayed, it will create a
A Lockscreen object is built, and the Lockscreen object is released when the lock screen disappears. However, if you forget to cancel the Phonestatelistener object that we previously registered when releasing the Lockscreen object, it will cause lockscreen to be garbage collected. If the lock screen interface is constantly displayed and disappears, it will eventually cause OutOfMemory due to the fact that a large number of Lockscreen objects have no way to be recycled, causing the system_process process to hang out. In short, when an object A with a shorter life cycle has its reference by a long-life object B, at the end of A's life cycle, a reference to A is cleared in B.

(v) Other
The most typical use of Android applications is to be aware of the need to release resources in the life cycle of the Activity, in the OnPause (), OnStop (), OnDestroy () methods, in the case of the appropriate release of resources. Since this is a very basic situation, it is not detailed here to see the official documentation on the Activity life cycle to determine when resources should be released.

Three, the characteristics of the non-robust code and solutions

1. Release the reference of the useless object as soon as possible. A good idea is to use a temporary variable when you leave the reference variable in the active field
, it is automatically set to null, implying that the garbage collector collects the object to prevent a memory leak.
For instances where pointers are still pointing, the JVM does not reclaim the resource because garbage collection will have null-valued objects
As garbage, improve the efficiency of GC recovery mechanism;

2, our program is inevitably a large number of use of string processing, avoid using string, should be used in large numbers

String 对象都得独立占用内存一块区域。String str = "aaa";String str2 = "bbb";String str3 = str + str2;//假如执行此次之后 str ,str2 以后再不被调用,那它
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4

will be placed in memory waiting for the Java GC to be recycled, too much in the program so the situation will be reported above the
Error, it is recommended that you use StringBuffer when using strings, so you can save a lot of
Distribution

3, minimize the use of static variables, because the static variables are global, the GC will not be recycled;

4, avoid the centralized creation of objects, especially large objects, the JVM will suddenly need a lot of memory, it will inevitably trigger GC optimization
system memory environment; The declared array space is displayed, and the number of requests is significant.
Use jspsmartupload for file upload, the operation of the process often appear java.outofmemoryerror
Error: The code in the component is found after the check

new byte[m_totalBytes];//问题原因是 totalBytes 这个变量得
    • 1
    • 2
    • 1
    • 2

To a large number, causing the array to allocate a lot of memory space, and the array will not be released in time.

5, try to use the object pool technology to improve the system performance; long-life objects with short life-cycle objects are easy to
When a memory leak is raised, such as when a large collection object has a business object with large data volumes, it can consider chunking for processing,
Then solve a piece of the strategy of releasing a piece.

6. Do not create objects in frequently invoked methods, especially when creating objects in loops. can be used appropriately
Hashtable,vector creates a set of object containers and then takes those objects from the container without each new
and then discarded.

7, generally occurs in the opening of large files or with the database once took too much data, resulting in the state of the memoryerror, this time about to calculate the maximum amount of data is how much, and set the required minimum and maximum memory space value.

Iv. Memory Leak monitoring Tool DDMS (Dalvik Debug Monitor Service:dalvik virtual Machine Debug Monitoring service)

Here I use the ADT plugin for Eclipse, and in the case of a real machine, it's similar in the simulator. The steps to use the heap to monitor the application process using memory are as follows:

    1. After you start eclipse, switch to the DDMS perspective and confirm that the Devices view, the Heap view, are open.
    2. Connect your phone to your computer via USB, and make sure your phone is in "USB debug" mode instead of
      To "Mass Storage".
    3. After the link is successful, the serial number of the mobile device is displayed in the Devices view of the DDMS, and the device
      Part of the process information that is running.
    4. Click to select the process that you want to monitor, the com.iflytek.inputmethod process of the flight input method.
    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:

Description
A) Clicking on the "Cause GC" button is equivalent to requesting a GC operation from the virtual machine;
b) When the memory usage information is displayed for the first time, the Heap view interface refreshes periodically without ever having to click on the "Cause GC", and changes in memory usage can be seen during the continuous operation of the application.

How do we know if our program has the possibility of a memory leak? Here's a value to note: Heap view
In the middle there is a type called data object, which is the object of a large number of class types that exist 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. It can be judged as follows:
A) continuously operate the current application, while observing the total Size value of the data object;
b) The total Size value will be stable in a limited range under normal circumstances, that is, because the code in the program is good, no object is not garbage collection, so that although our continuous operation will continue to generate a lot of objects, and in the process of virtual machine continuous GC, These objects are recycled, and the memory footprint will fall to a steady level;
c) Conversely, if there is a case in the code that does not release the object reference, the total size value of the data object does not come down significantly after each GC, and as the number of operations is increased, the value of total size becomes larger until an upper limit is reached, causing the process to be killed.

V. Memory Leak analysis tool MAT (Analyzertool)

MAT is an Eclipse plugin, official: http://download.eclipse.org/mat/1.1/update-site/.

(i) Generate a. hprof file

    1. Open Eclipse and switch to the DDMS perspective, confirming that the Devices, Heap, and LogCat views are open.
    2. Link your phone device to your computer and make sure to use the USB debug mode link instead of the Mass Storage mode.
    3. After the link is successful, you will see the serial number of the device in the Devices view, and the part of the process that is running on the device.
    4. Click to select the process for the app you want to analyze, and in the Row icon button above the Devices view, select both the Update Heap and Dump HPROF file two buttons. The DDMS tool will automatically generate the. hprof file for the currently selected process:

(ii) using the MAT to import. hprof files

Click Windows->open perspective->other->memory Analyzer in Eclipse, or the RCP with the Memory Analyzer Tool. In the MAT, click File->open File to browse and import the. hprof files you just converted.

(iii) Analyze memory using the MAT's view tool

    1. After importing the. hprof file, MAT automatically parses and generates reports, clicks Dominator Tree, and groups by package.
    2. Select your own defined package class right-click and select list Objects->with incoming references in the pop-up menu. All suspicious classes are listed, right-click on an item and select Path to GC Roots
      Exclude Weak/soft references will further filter out all memory-leaking classes associated with the program. As a result, you can trace to a class in your code that produces a leak.

In summary, the fundamental idea of using MAT to analyze memory for memory leaks is to find out which class object references have not been freed, to find out why they are not being released, and to easily locate which fragments in the code are logically problematic.

As shown, "Problem Suspect" can be a place where there is a memory leak in the code.

Android Memory leak debug

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.