Android common memory leaks & Solutions

Foreword

Memory leaks (Memory Leak) refers to the program has been dynamically allocated heap memory for some reason the program does not release or not release, resulting in a waste of system memory, causing the program to run slowly or even crash (OOM) and other serious consequences.

That can not be recovered under what circumstances it?

Currently the mainstream java garbage collection algorithm is a virtual machine using GC Roots Tracing algorithms. The basic idea of ​​the algorithm is: a set of objects called by GC Roots (GC root) as a starting point, a node from which to start the search down the search path traversed, when an object has no references to GC Roots chain connected (FIG discourse: GC Roots from the object to not reachable), it proves that the object is not available.

About reachability object, the object can be constructed is a connected graph and GC Roots, as shown below:

Write pictures described here

The basic idea of ​​the root of the search algorithm is a series of objects called "GC Roots" as a starting point, to start the search downward from these nodes, called search path traversed reference chain (Reference Chain), when an object to GC Roots without any reference chain joined, then prove that this object is not available.

From the FIG., Reference1, reference2, reference3 are GC Roots, it can be seen:

reference1-> 1 object instance;

reference2-> 2 object instance;

reference3-> 4 object instance;

reference3-> object instance 4 -> 6 object instance;

1,2,4,6 can be drawn object instances have GC Roots accessibility, that is, live objects, objects that can not be recovered GC.

For instance, although direct communication objects 3,5, but none GC Roots connected thereto, which is the GC Roots unreachable object, which is GC need to recycle garbage objects.

After understanding GC, memory leaks begin to understand the situation of the Android.

Android scene memory leaks 

 The following will detail some of the common memory leaks scene, as well as the corresponding repair measures.

 Examples of non-static static inner class

For example, we define an inner class inside InnerClass Activity, at the same time defines a static variable inner, and given the assignment. Assuming you have not null in the inner set onDestory time; it will cause a memory leak. The reason is that static variable to hold the instance of the inner class, inner class will have a reference to the outer class, resulting in Activity not released.

    private static Object inner;
       
        void createInnerClass() {
           class InnerClass {
            } 
           inner = new InnerClass();
        }
    
    View icButton = findViewById(R.id.ic_button);
    icButton.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View v) {
            createInnerClass();
            nextActivity();
        }
    });

I remember at the end of the life cycle, you will not need a static variable set null.

Multi-thread-related anonymous inner class / non-static inner classes

And non-static inner classes, anonymous inner class will hold a reference to the outer class instance. Multithreading AsyncTask class associated with a class, the Thread class Runnable interface and the like, if they do anonymous inner classes consuming operations
on the memory leak may occur, where to exemplified AsyncTask anonymous inner classes, as follows:

    void startAsyncTask() {
        new AsyncTask<Void, Void, Void>() {
            @Override protected Void doInBackground(Void... params) {
                while(true);
            }
        }.execute();
    }
    
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    View aicButton = findViewById(R.id.at_button);
    aicButton.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View v) {
            startAsyncTask ();
            nextActivity();
        }
    });

When during an asynchronous task execution time-consuming tasks in the background, Activity unfortunately been destroyed (for example: the user exits the system recovery), which was held AsyncTask Activity instance will not be garbage collected until the end of asynchronous tasks.
The solution is to create a succession AsyncTask static inner class, create an instance there would not be a reference to the examples of the external static inner classes.

 

Handler memory leaks

Similarly, the message is transmitted to the Handler message queue  MessageQueue , the  Message prior message was not processed, nor examples handler can not be recovered, if not static handler instance, will lead to its activity or reference service can not be recovered, then a memory leak occurs.

    void createHandler() {
        new Handler() {
            @Override public void handleMessage(Message message) {
                super.handleMessage(message);
            }
        }.sendMessageDelayed(Message.obtain(), 60000);
    }
    
    
    View hButton = findViewById(R.id.h_button);
    hButton.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View v) {
            createHandler();
            nextActivity();
        }
    });

 For these problems, there are two solutions, one is to use a static handler inner class, and the object of its holdings have changed the form of weak references cited. When there is a destruction activity will be removed messages sent.

myHandler.removeCallbackAndMessages(null);

This is a question Handler messages may not all be processed.

Another thing to notice is best not to directly use the View # post to do some operations. If you do, make sure to use it, make sure that view has been attach to the window.

Specific reference may be: POST method View memory leak analysis results

Static or View Activity

Defined in the static class Activity variables, the current running Activity instance assigned to the static variables.
If the static variable Activity is not empty after the end of the life cycle, it causes a memory leak. Because static variable throughout the life cycle of the application, so the leak  Activity  will always exist in the application process will not be garbage collected.
static Activity activity;
    
    void setStaticActivity() {
      activity = this;
    }
    
    View saButton = findViewById(R.id.sa_button);
    saButton.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View v) {
        setStaticActivity();
        nextActivity();
      }
    });

In order to be able to be recovered, the need for null set operation time is not required. For example, when the destruction of the current activity.

Special case: If a View initialize a lot of resources, but also in a  Activity life cycle remains the same, then you can turn it into a static, loaded onto a tree view (View Hierachy), like this, when  Activity the time is destroyed, it should release resources .

static view;
    
    void setStaticView() {
      view = findViewById(R.id.sv_button);
    }
    
    View svButton = findViewById(R.id.sv_button);
    svButton.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View v) {
        setStaticView();
        nextActivity();
      }
    });

Similarly, in order to solve the problem of memory leaks, destroyed when the Activity of this static view is set to null, but still we do not use this method static view of the proposal.

Eventbus and other registered listeners caused by a memory leak

I believe that many students are in the project which will be used Eventbus. For some students did not experience some of the problems often occur when in use. For example, in the onCreate when registered, but forgot the anti-registration, or that the anti-onStop registered in time, which can lead to memory leaks Eventbus of.

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    EventBus.getDefault () Register (. The this ); // Note registered in onCreate () method 
}

@Override
public void onDestroy() {
    EventBus.getDefault () the unregister (. The this ); // Note onDestory () method registered 
    Super .onDestroy ();
}

Registration and anti-registration (cancellation of registration) is the corresponding need to be added, otherwise it will cause a memory leak components. Since the time of registration assemblies are held inside the queue referenced single embodiment of EventBus.

If you are a registered Eventbus in View inside, remember to register and unregister in the life cycle of View onAttachedToWindow and onDetachedFromWindow time.

Recently time to chat with my colleagues found them in order to solve the memory leak problem eventbus due (already paired registration and the registration or memory leak problem), he intended to create an instance of the object, and use this to register and counter registration, so that even if a memory leak occurs it will only take up very little memory space.

Singleton memory leaks caused by

Projects, often there are many single cases. Sometimes we need to pass the current Activity singleton instance, and then do something about it. The following code:

public class SingleInstance {
    private Context mContext;
    private static SingleInstance instance;
 
    private SingleInstance(Context context) {
        this.mContext = context;
    }
 
    public static SingleInstance getInstance(Context context) {
        if (instance == null) {
            instance = new SingleInstance(context);
        }
        return instance;
    }
}

 The above example passed a single context, as it will lead to a long life-time and long-life context of the application. It will cause a memory leak.

For this there are three solutions:

1, by way of weak reference is a reference to ensure that can be recovered;

2, when the corresponding context to be destroyed, were set to null; ensure a long time will not be longer than the original life;

3, to see whether the use of APP context; so there is no problem of a memory leak.

Did not close the resource object causes a memory leak

When we open the resource, usually using the cache. Resources such as read and write files, open the database resources, use of resources, etc. Bitmap. When we no longer use, they should be closed so that the cache memory region timely recovery. Although some objects, if we do not shut down its own in the finalize () function will shut itself down. But it was only until the close GC recovery, this will lead to the cache residence for some time. If we frequently open resource, memory leaks caused by the impact is more obvious.

Solution: close the resource

 

WebView 

Different versions of the Android webView vary, plus webView differences manufacturers custom ROM, which results in the presence of a lot of compatibility issues webView. weView there will be a memory leak problem, just used once, the memory will not be released in the application. The usual practice is to open a single webView process, the main process AIDL using interprocess communication and application. webView process may be destroyed or burned at the right time based on business needs.

 

 references:

1, "Android Advanced decrypt"

2, Android eight possible memory leak 

 

Guess you like

Origin www.cnblogs.com/huansky/p/11806689.html