Android Memory leakage and debugging

Source: Internet
Author: User
Reprinted: http://android-zhang.iteye.com/blog/1562791
I. Android memory mechanism
Android Program It is written in Java, so the memory management of Android is similar to that of Java. The programmer allocates memory for the object through new, and all objects are allocated space in the Java heap. However, the release of the object is done by the garbage collector.
How can GC check whether an object has been deprecated? Java adopts the principle of Directed Graphs. Java considers the reference relationship as directed edges of a graph, and directed the directed edge from the quotor to the referenced object. A thread object can be used as the starting vertex of a directed graph. This graph is a tree starting from the starting vertex. All objects that can be reached by the root vertex are valid objects and GC will not recycle these objects. If an object (connected subgraph) is inaccessible to this root vertex (note that this graph is a directed graph), we think this (these) object is no longer referenced and can be recycled by GC.

Ii. Android memory overflow
How does Android memory overflow occur?
The android virtual machine is a register-based Dalvik. Its maximum heap size is generally 16 m, and some machines are 24 m. Therefore, the memory space we can use is limited. If our memory usage exceeds a certain level, an outofmemory error occurs.
Why is memory insufficient? I think there are two main reasons:
Due to program errors, some resources (such as context) can be referenced for a long time, resulting in Memory leakage and unreleased resources.
Saves multiple objects (such as Bitmap) that consume too much memory, resulting in memory exceeding the limit.

Iii. Common memory leaks
1. Static
Static is a keyword in Java. When it is used to modify a member variable, the variable belongs to the class, rather than the instance of the class. Therefore, the life cycle of a variable modified with static is very long. If you use it to reference some instances that consume too much resources (the case of context is the most), you should be cautious.

Public class classname {
Private Static Context mcontext; // omitted
}
The aboveCodeIt is very dangerous, if the activity is assigned to mcontext. Even if the activity has been ondestroy, the activity will not be released because there are still objects that store its reference.

How can we effectively avoid such a reference?
First, we should try our best to avoid using static member variables to reference instances that consume too much resources, such as context.
Second, use the application context whenever possible. Because the application context has a long life cycle, it will not cause memory leakage if referenced.
Third, use weakreference instead of strong reference. For example, you can use weakreference Mcontextref;

2. Troubles caused by threads
Threads are also an important source of Memory leakage. The main cause of thread Memory leakage is the uncontrollable thread lifecycle. Let's consider the following code.
Public class myactivity extends activity {
@ Override
Public void oncreate (bundle savedinstancestate ){
Super. oncreate (savedinstancestate );
Setcontentview (R. layout. Main );
New mythread (). Start ();
}
Private class mythread extends thread {
@ Override
Public void run (){
Super. Run ();
// Do somthing
}
}
}
This code is usually very simple and is often used. Let's think about a problem: assume that the run function of mythread is a very time-consuming operation. When we enable this thread, we change the horizontal screen of the device to a vertical screen, generally, when the screen is switched, the activity will be re-created. According to our ideas, the old activity should be destroyed. However, this is not the case.
Because our thread is an internal class of activity, a reference of activity is saved in mythread. When the run function of mythread is not completed, mythread will not be destroyed, therefore, the old activity referenced by it will not be destroyed, so Memory leakage occurs.

How should we solve the memory leakage caused by such threads?
First, change the internal class of the thread to the static internal class.
Second, use weak references within the thread to save context references.

In addition, we all know that hanlder is a bridge between threads and activities. We will use threads in many applications. Some users may improperly handle the issue and cause the program to end, the thread is not destroyed, but is always running in the background. When we restart the application, a thread will be restarted again and again. The more times you start the application, the more threads you open, the slower your machine will become.
Package com. Tutor. thread;
Import Android. App. activity;
Import Android. OS. Bundle;
Import Android. OS. Handler;
Import Android. util. log;
Public class threaddemo extends activity {
Private Static final string tag = "threaddemo ";
Private int COUNT = 0;
Private handler mhandler = new handler ();

Private runnable mrunnable = new runnable (){

Public void run (){
// Log is printed for ease of viewing.
Log. E (TAG, thread. currentthread (). getname () + "" + count );
Count ++;
Settitle ("" + count );
// Execute every 2 seconds
Mhandler. postdelayed (mrunnable, 2000 );
}

};
@ Override
Public void oncreate (bundle savedinstancestate ){
Super. oncreate (savedinstancestate );
Setcontentview (R. layout. Main );
// Start the thread through Handler
Mhandler. Post (mrunnable );
}

}
So when the application exits, we need to destroy the thread. As long as the ondestory () method in the activity is processed, it will be OK, as shown in the following code:
@ Override
Protected void ondestroy (){
Mhandler. removecallbacks (mrunnable );
Super. ondestroy ();
}

3. Super fat bitmap
It can be said that the vast majority of people who encounter the outofmemory problem are due to the bitmap problem. Because bitmap occupies too much memory, it is a "super fat man", especially a high-resolution image. If you want to display multiple images, the problem is even more significant.

How can we solve the memory problems brought by bitmap?

1. Timely destruction.
Although the system can confirm that the memory allocated by bitmap will eventually be destroyed, it may exceed the Java heap limit because it occupies too much memory. Therefore, when using bitmap, You need to delete the recycle in time. Recycle is not sure that bitmap will be released immediately, but it will imply to the Virtual Machine: "The image can be released ".

Second, set a certain sampling rate.
Sometimes, the area we want to display is very small and it is not necessary to load the entire image. Instead, we only need to record a reduced image. At this time, we can set a certain sampling rate, therefore, the occupied memory can be greatly reduced. The following code:
Private imageview preview;
Bitmapfactory. Options = new bitmapfactory. Options ();
Options. insamplesize = 2; // The image width and height are 1/2 of the original image, that is, the image is 1/4 of the original image.
Bitmap bitmap = bitmapfactory. decodestream (Cr. openinputstream (URI), null, options); preview. setimagebitmap (Bitmap );

Third, use softrefrence)
Sometimes, we do not retain references to bitmap, so we cannot call the recycle function. By using soft references, bitmap can be effectively released when the memory is insufficient.

4. Unusual cursor
Cursor Is a class used to manage data sets after data is queried by Android. Normally, if the queried data volume is small, there will be no memory problems, moreover, the virtual machine can ensure that the cusor will be released eventually.
However, if the data size of the cursor table is large, especially if blob information exists, the memory occupied by the cursor should be promptly released, rather than waiting for GC to process. In addition, Android obviously prefers programmers to manually close the cursor.

5. When constructing the adapter, the cached convertview is not used
Description:
Taking constructing the baseadapter of listview as an example, the method is improved in baseadapter:
Public View getview (INT position, view convertview, viewgroup parent)
To provide listview with the view object required by each item. Initially, the listview will instantiate a certain number of view objects from the baseadapter based on the current screen layout, and the listview will cache these view objects. When you scroll up the listview, the view object originally located in the top list item will be recycled and then used to construct the bottom list item that appears. This construction process is completed by the getview () method, getview () the second view convertview parameter is the view object of the cached list item. (convertview is null if no view object is cached during initialization ).
From this we can see that if we don't use convertview, but re-instantiate a view object in getview () every time, it will be a waste of resources and time, which will also increase the memory usage. You can view the process when listview recycles the view object of list item:
Android. widget. abslistview. Java --> void addscrapview (view scrap) method.
Sample Code:
Public View getview (INT position, view convertview, viewgroup parent ){
View view = new XXX (...);
......
Return view;
}
Corrected 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;
}

Summary:
Static: References large objects such as context
Thread: when the screen is switched, the activity is not destroyed as scheduled because of thread reference; handler is related, activity is terminated unexpectedly, but the thread is still
Bitmap: Timely recycle to reduce Sampling Rate
Cursor: close it in time
Adapter: convertview without Cache

Iv. Memory Leak debugging:
(1). Memory monitoring tool ddms --> heap
No matter how careful you are, it is impossible to completely avoid bad code. At this time, some tools are required to help us check whether there is any place in the code that will cause memory leakage. The ddms in Android tools comes with a very good memory monitoring tool heap (here I use the ADT plug-in of eclipse, and take the real machine as an example, the situation in the simulator is similar ). To monitor the memory usage of an application process using heap, follow these steps:
1. After eclipse is started, switch to the ddms perspective and confirm that the devices view and heap view are all open;
2. Connect your phone to your computer via USB. Make sure that the phone is in "USB debugging" mode instead of "Mass Storage ";
3. After the connection is successful, the device serial number and running process information are displayed in the devices view of ddms;
4. Click the process you want to monitor, such as the system_process process;
5. Click the "Update Heap" icon in the top row of the selected devices View Interface;
6. Click "cause GC" in the heap view;
7. In the heap view, the details of the memory usage of the selected process are displayed.
Note:
A) clicking the "cause GC" button is equivalent to requesting a GC operation from the VM;
B) when the memory usage information is displayed for the first time, you do not need to constantly click "cause GC". The heap view interface will be refreshed on a regular basis, the changes in memory usage can be seen during the continuous operation of applications;
C) the parameters of the memory usage information can be known Based on the name and will not be described here.
How can we know whether our program has the possibility of Memory leakage. Here, you need to pay attention to a value: In the heap view, there is a type called data object, that is, the data object, that is, a large number of class type objects in our program. In a row of data object, there is a column named "total size", whose value is the total memory of all Java Data Objects in the current process. Generally, the size of this value determines whether memory leakage exists. You can judge this as follows:
A) constantly operate on the current application, and observe the total size value of the data object;
B) under normal circumstances, the total size value will be stable within a limited range. That is to say, because the code in the program is good, the object will not be garbage collected, therefore, although we continuously generate many objects during operations, these objects are recycled during the continuous GC of virtual machines, memory usage will reach a stable level;
C) if the Code does not release the object reference, the total size value of the data object will not be significantly reduced after each GC, as the number of operations increases, the value of total size increases,
The process is killed until the upper limit is reached.
D) The system_process process is used as an example. In my testing environment, the total size of the Data Object occupied by the system_process process will normally be 2.2 ~ 2.8, and when the value exceeds 3.55, the process will be killed.

In short, using the heap View tool of ddms can easily confirm whether our program has the possibility of Memory leakage.

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.