Android Memory Leak summary

Source: Internet
Author: User

Introduction:
Between *java and C + + there is a wall of memory allocation and garbage collection technology that people outside the wall want to come in and the people inside the wall want to come out.
For developers engaged in C and C + + program development, in the field of memory management, they are both the highest power of the emperor, but also engaged in the most basic work of the working people;
Ownership of each object, and the maintenance responsibility of the beginning of life to the end of each object.
For Java programmers, with the help of a virtual machine's automatic memory management mechanism, it is no longer necessary to write paired Delete/free code for each new operation;
And it's not easy to have a memory leak and a memory overflow problem. It looks like the memory is managed by the virtual machine everything is fine;
However, it is because the Java programmer has given the power of memory control to the Java Virtual machine,
In the event of a memory leak and overflow problem, if you do not know how the virtual machine is using memory, the troubleshooting error will be an extremely difficult task.
--Zhou Zhiming "in-depth understanding of Java virtual machines"

Android Memory Leak Summary

The purpose of memory management is to enable us to effectively avoid the problem of memory leak in our application and improve the experience and quality of the application in coding. A memory leak is a release of an object that has not been released and has been held by some or some instances and is no longer being used, causing the GC to not be recycled.
Android uses the Java language, first of all, let's look at the principle of Java memory leak.

A. Java memory allocation policy

Java Program runtime memory allocation policy has three kinds, namely static allocation, stack allocation, and heap allocation,
Corresponding, the memory space used by three storage policies is mainly static storage (also called method area), stack area and heap area.

Static Storage area (method area):
It mainly stores static data, global static data, and constants.
This block exists when the program is compiled, and it is present during the entire run of the program.

Stack area:
When the method is executed, local variables in the method body are created on the stack and the memory held by these local variables is automatically freed at the end of the method execution.
Because the stack memory allocation operation is built into the processor's instruction set, it is highly efficient, but the allocated memory capacity is limited.

Heap Area:
Also known as dynamic memory allocation, usually refers to the memory that is directly new when the program is running.
The Java garbage collector will be responsible for recycling this part if it is not in use.

Stack-to-heap differences:

Variables defined in the method body (local variables) and reference variables of some basic types are allocated in the stack memory of the method.
When a variable is defined in a block of methods, Java allocates memory space for the variable in the stack, and when the scope of the variable is exceeded,
The variable is also invalid, and the memory space allocated to it will be freed up and the memory space can be reused.

Heap memory is used to hold all objects created by new (including all member variables of the object) and arrays.
The memory allocated in the heap is automatically managed by the Java garbage collector.
After creating an array or an object in the heap, you can also define a special variable in the stack that is equal to the array or the first address of the object in the heap memory, and this particular variable is the reference variable that we refer to above.
We can use this reference variable to access objects or arrays in the heap.

As an example:

publicclassSample() {    int0;    new Sample();    publicvoidmethod() {        int1;        new Sample();    new Sample();

The local variable s2 and reference variable mSample2 of the Sample class are present on the stack, but the object that the MSample2 points to is present on the heap.
The object entity that MSample3 points to is stored on the heap, including all member variables S1 and mSample1 of the object, and it exists on the stack itself.

Conclusion:

The base data types and references for local variables are stored in the stack, and the referenced object entities are stored in the heap.
-because they belong to the variables in the method, the life cycle ends with the method.

Member variables are all stored with the heap (including the base data type, referenced and referenced object entities)
-because they belong to the class, the class object is eventually used by new.

After understanding the memory allocation in Java, let's look at how Java manages memory.

Second, Java is how to manage memory

The memory management of Java is the allocation and release of objects.
In Java, programmers need to request memory space for each object through the keyword new (except for the base type), and all objects allocate space in the heap.
In addition, the release of the object is determined and executed by the GC.
In Java, the allocation of memory is done by the program, and the release of memory is a GC, the two lines of the method does simplify the work of the programmer.
At the same time, it adds to the work of the JVM, which is one of the reasons why the Java program is running slower.
Because, in order for the GC to properly dispose of objects, the GC must monitor the running state of each object, including the application, reference, reference, assignment, etc. of the object, which the GC needs to monitor.

The object's state is monitored to release the object more accurately and in a timely manner, and the fundamental principle of releasing the object is that the object is no longer referenced.

To better understand how the GC works, we can consider the object as a vertex of the directed graph, consider the reference relationship as a directed edge of the graph, and have a directed edge from the referrer to the cited object.
In addition, each thread object can be used as the starting vertex of a graph, for example, when most programs are executed from the main process, the graph is a root tree that starts with the main process vertex.
In this graph, the object that the root vertex can reach is a valid object, and the GC will not reclaim those objects.
If an object (connected sub-graph) and this root vertex are unreachable (note that the graph is a forward graph), then we think that this (these) objects are no longer referenced and can be recycled by GC.
Below, let's give an example of how memory management is represented by a graph.
For every moment of the program, we have a graph of graphs that represent the memory allocations of the JVM.
On the right, the left program runs to line 6th.

Java uses a graph-like approach to memory management, which eliminates the problem of reference loops, such as having three objects and referencing each other, so that GC can reclaim them as long as they are unreachable from the root process.
The advantage of this approach is that the precision of managing memory is high, but the efficiency is low.
Another common memory management technique is the use of counters, such as the COM model, which uses counter-mode management artifacts, which are low-precision rows (difficult to handle circular references) compared to a forward graph, but perform efficiently.

Iii. What is a memory leak in Java

In Java, the memory leak is the existence of some assigned objects, these objects have the following two characteristics, first of all, these objects are accessible, that is, in the graph, the existence of the path can be connected;
Second, these objects are useless, that is, the program will no longer use these objects.
If the object satisfies both conditions, these objects can be judged as a memory leak in Java, which is not reclaimed by the GC, but it consumes memory.

In C + +, memory leaks are larger in scope.
Some objects are allocated memory space, and then unreachable, because there is no GC in C + +, the memory will never be returned.
In Java, these unreachable objects are collected by the GC, so programmers do not need to consider this part of the memory leak.
Through the analysis, we learned that for C + +, programmers need to manage their own edges and vertices, and for Java programmers only need to manage the edge (do not need to manage the release of vertices).
In this way, Java improves the efficiency of programming.

So, with the above analysis, we know that there is also a memory leak in Java, but the scope is smaller than C + +.
Because Java is guaranteed by the language that any object is accessible, all unreachable objects are managed by the GC.

For programmers, GC is basically transparent and invisible.
Although we have only a few functions that can access the GC, such as the function System.GC (), which runs the GC, the function does not guarantee that the JVM's garbage collector will execute, as defined by the Java language Specification.
Because different JVM implementations may use different algorithms to manage the GC.
Typically, a GC's thread has a lower priority level. There are a number of policies that the JVM calls the GC, some of which are used to a certain extent, the GC starts to work, there are timed executions, there is a gentle execution of the GC, and some interrupt-execution GC.
But generally, we don't need to care about this, except in some specific situations, the execution of the GC affects the performance of the application.
For example, for Web-based real-time systems, such as online games, users do not want the GC to suddenly interrupt application execution for garbage collection,
Then we need to adjust the GC parameters so that the GC can free up memory in a gentle way,
For example, by decomposing garbage collection into a series of small steps, the sun-provided hotspot JVM supports this feature.

Also gives a typical example of a Java memory leak,

new Vector(10);for (int1100; i++) {    ObjectnewObject();    v.add(o);    null;}

In this example, we iterate over the object and put the requested object into a Vector, if we just release the reference itself,
Then the Vector still references the object, so this object is not recyclable to the GC.
Therefore, if the object has to be removed from the vector after it has been added to the vector, the simplest way is to set the vector object to null.

Iv. Summary of memory leaks common in Android

1. Memory leak caused by single case

The singleton mode is very popular with developers, but using inappropriate words can also cause memory leaks, because the static nature of the singleton makes the life cycle of the singleton as long as the lifetime of the application, which means that if an object is no longer needed, the Singleton object also holds a reference to the object. Then this object will not be properly recycled, which results in a memory leak.
The following example:

publicclass AppManager {  privatestatic AppManager instance;  private Context context;  privateAppManager(Context context) {    this.context = context;  }  publicstaticgetInstance(Context context) {    ifnull) {      new AppManager(context);    }    return instance;  }}

This is an ordinary singleton pattern, and when this singleton is created, the length of the context's life cycle is critical because of the need to pass in a context:

1, the incoming is the application context: This will not have any problems, because the life cycle of the singleton and application the same length

2. The context of the activity is passed in: when the activity of this context is exited, because the context is as long as the activity's life cycle (activity indirectly inherits from the context),
So the current activity exits when its memory is not recycled because the Singleton object holds a reference to the activity.

So the correct singleton should be modified to the following way:

 public   Class  AppManager {private  static     AppManager instance; private     Context context; private  appmanager  () {this . Context = Myapplication.getcontext ();    //using application's context } public  static  AppManager getinstance  () {if  (instance = = null ) {instance = new  AppManager ();        } return  instance; }    }

This way, no matter what context is passed in, the application context will eventually be used, and the life cycle of the singleton is as long as the application, thus preventing a memory leak.

2. A non-static internal class creates a memory leak caused by a static instance

There are times when we may be able to start frequent activity, in order to avoid duplicating the same data resources, this might be the case:

 Public  class mainactivity extends Activity {  Private StaticTestresource Mresource =NULL;@Override  protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); Setcontentview (R.layout.activity_main);if(Mresource = =NULL) {Mresource =NewTestresource (); }//...} class Testresource {//...}}

This creates a single instance of a non-static inner class within the activity, which uses the singleton data every time the activity is started, which avoids duplication of resources, but is a memory leak because non-static inner classes hold references to external classes by default.
The non-static inner class creates a static instance with the same life cycle as the application, which causes the static instance to hold a reference to the activity, which causes the activity's memory resource not to be recycled properly.

The right approach is:
Set the inner class as a static inner class or extract the inner class into a single case, if you need to use the context, follow the recommended context for using application.
Of course, the context of application is not omnipotent, so it can not be arbitrarily used, for some places must use the context of Activity;
The context scenario for application,service,activity is as follows:

3. Memory leak caused by handler

The memory leak problem caused by the use of handler should be said to be the most common, usually in the processing of network tasks or encapsulation of some request callback API should be handled with the help of handler,
The use of handler code to write a non-standard is likely to cause a memory leak, such as the following example:

 Public  class sampleactivity extends Activity {    Private FinalHandler Mleakyhandler =NewHandler () {@Override         Public void Handlemessage(Message msg) {// ...}    };@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); Mleakyhandler.postdelayed (NewRunnable () {@Override             Public void Run() {/**                 *                 **/}        }, +* -*Ten);    Finish (); }}

In the sampleactivity, a message that was deferred for 10 minutes was declared Message,mleakyhandler push it into the message queue MessageQueue.
When the activity is dropped, a Message that delays the execution of the task will continue to exist in the main thread, which holds the Handler reference to the activity.
So at this point, the Activity of finish () will not be recycled and thus cause a memory leak (because Handler is a non-static inner class, it holds references to external classes, in this case refers to sampleactivity).

Repair method:
Avoid using non-static inner classes in Activity, such as above, where we declare Handler as static, its survival is irrelevant to the life cycle of the activity.
At the same time, the activity is introduced by means of weak reference, so as to avoid directly passing activity as context.
This avoids the activity leak, but the message queue of the Looper thread is still a message that might be processed.
So we should remove the message in the message queue at the time of the activity's destroy or stop, more precisely as follows:

 Public  class sampleactivity extends Activity {    Private Static  class myhandler extends Handler {        Private FinalWeakreference<sampleactivity> mactivity; Public MyHandler(sampleactivity activity) {mactivity =NewWeakreference<sampleactivity> (activity); }@Override         Public void Handlemessage(Message msg) {Sampleactivity activity = mactivity.get ();if(Activity! =NULL) {// ...}        }    }Private FinalMyHandler Mhandler =NewMyHandler ( This);Private Static FinalRunnable srunnable =NewRunnable () {@Override         Public void Run() {/* ... */}    };@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); Mhandler.postdelayed (Srunnable, +* -*Ten);    Finish (); }@Override      protected void OnDestroy() {Super. OnDestroy (); Mhandler.removecallbacksandmessages (NULL); }}

4. Memory leak caused by thread

The memory leaks that are caused by threads are usually common, as the following two examples may be written by everyone:

//test1    NewAsynctask<Void,Void,Void>() {@Overrideprotected VoidDoinbackground (Void... params) {Systemclock.Sleep10000);return NULL; }    }.Execute ();//test2    New Thread(NewRunnable () {@Override Public voidRun () {Systemclock.Sleep10000); }    }).Start ();

Both the async task and the runnable are an anonymous inner class, so they have an implicit reference to the current activity.
If the task is not completed before the activity is destroyed, the memory resource of the activity cannot be reclaimed, causing a memory leak.
The correct approach is to use static internal classes in the following way:

 Static  class myasynctask extends asynctask<void, void,  Void> {    PrivateWeakreference<context> WeakReference; PublicMyasynctask (Context context) {WeakReference =NewWeakreference<> (context); } @Overrideprotectedvoid Doinbackground (void ... params) {Systemclock.sleep (10000);return NULL; } @Overrideprotected voidOnPostExecute (Void aVoid) {Super. OnPostExecute (AVoid); Mainactivity activity = (mainactivity) weakreference.get ();if(Activity! =NULL) {//...}    }  }Static  class myrunnable implements Runnable{@Override Public voidRun () {Systemclock.sleep (10000); }  }//——————  NewThread (NewMyrunnable ()). Start ();NewMyasynctask ( This). Execute ();

This avoids the activity of memory resource leakage, of course, when the activity is destroyed should also cancel the corresponding task Asynctask::cancel (), to avoid tasks in the background waste resources.

5. Memory leaks due to resource not shutting down

For use of resources such as Braodcastreceiver,contentobserver,file,cursor,stream,bitmap,
Should be closed or logged off when the activity is destroyed, otherwise these resources will not be recycled, causing a memory leak.

Some suggestions:
1. References to activity and other components should be controlled within the activity's life cycle;
If it is not possible to consider using Getapplicationcontext or getapplication, to prevent the Activity from being compromised by an object reference to the external minister's life cycle.

2, try not to use static variables or static internal classes with non-static external member variables (including context), even if you want to use, but also to consider the appropriate time to empty the external member variables, you can also use weak references in the inner class to refer to the variables of the outer class.

3. For an internal class object with a longer life cycle than the activity, and the internal class uses the member variables of the outer class, you can do this to avoid a memory leak:
A) change the inner class to a static inner class
b) Use weak references in static inner classes to refer to member variables of external classes

4, Handler of the Reference object is best to use a weak reference, the resource can also be released when the Handler inside the message.
For example, when Activity onStop or OnDestroy, cancel the message and Runnable of the Handler object.

5, in the Java implementation process, but also to consider its object release, the best way is not to use an object, the object is explicitly assigned to NULL, such as the use of bitmap after the first call recycle (), and then assigned to NULL, Empty arrays that have direct or indirect references to resources such as images (using array.clear (); Array = null), etc., it is best to follow the principles of who created who released.

6, the correct shutdown of resources, for the use of Braodcastreceiver,contentobserver,file, cursor cursor,stream,bitmap and other resources used, should be in the activity when the destruction of the timely closure or logoff.

7, keep the object life cycle sensitive, pay special attention to the life cycle of single case, static object, global collection and so on.
Reference: cloud-dwelling communities

Android Memory Leak summary

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.