preface

  • inAndroidMemory leakage is very common. And the memory leak will lead to the consequences of the applicationCrash
  • This article provides a comprehensive overview of the nature, causes and solutions of memory leaks, and finally provides some common memory leak analysis tools that you will enjoy.

directory


Schematic diagram


1. Introduction

  • namelyML (Memory Leak)
  • Memory is memory that cannot be released and returned to a program when it is no longer needed

2. Impact on applications

  • It is easy for the application to run out of memory, i.eOOM

Introduction to memory overflow:




Schematic diagram


3. The root cause of memory leakage

  • A detailed description


Schematic diagram

  • Pay special attention to

    From a mechanical point of view, becauseJavaGarbage collection mechanisms exist (GC), there should be no memory leaks; Memory leaks occur only because of external human causes =Object references are held unconsciously such that the life cycle of the holder is greater than the life cycle of the referenced

4. Knowledge: Android memory management mechanism

4.1 introduction


Schematic diagram

In the following sections, we will go into details about memory allocation & reclamation for recycling processes, objects, and variables

4.2 Memory Policies for Processes

A. Memory allocation policy

Memory allocation for all processes is centrally managed by ActivityManagerService

B. Memory reclamation policy

  • Step 1:Application FrameworkDetermines the type of process to recycle

    Processes in Android are managed; When process space is limited, processes are automatically reclaimed in the order of low -> high priority

Android classifies processes into five priority levels, as follows:


Schematic diagram

  • Step 2:LinuxThe kernel actually recycles specific processes
    1. ActivityManagerServiceAll processes are scored (scores are stored in variablesadjC)
    2. Update score toLinuxThe kernel
    3. byLinuxThe kernel does true memory reclamation

Here only summarizes the process, the process of the complex, interested readers can research system source ActivityManagerService. Java

4.2 Memory Policies for Objects and variables

  • AndroidThe memory strategy for objects and variables is the sameJava
  • Memory management = memory allocation of objects/variables + memory release

In the following sections, the memory allocation & memory free strategy will be explained in detail

A. Memory allocation policy

  • The memory allocation of objects/variables is taken care of automatically by the program
  • There are three types of allocation: static allocation, stack allocation, & heap allocation, respectively for static variables, local variables & object instances
  • The details are as follows


Schematic diagram

Note: Use an example to explain memory allocation

public class Sample { int s1 = 0; Sample mSample1 = new Sample(); Public void method() {public void method() {public void method() {public void method() 0; Sample mSample2 = new Sample(); MSample3 = new Sample(); mSample3 = new Sample();Copy the code

B. Memory release policy

  • Object/variable memory freed byJavaGarbage collector (GC)/frame stack is responsible
  • The focus here is on the memory free strategy of object allocation (heap allocation) =JavaGarbage collector (GC)

Because static allocation does not need to release, stack allocation only through the frame stack automatically out, onto the stack, relatively simple, so it is not described in detail

  • JavaGarbage collector (GC) = garbage collection algorithm, mainly including:


Garbage collection algorithm type

  • The details are as follows


conclusion


5. Common Causes of memory leaks & Solutions

  • Common causes of memory leaks are as follows:
  1. Collection classes
  2. StaticThe keyword modifies the member variable
  3. Non-static inner class/anonymous class
  4. The resource object is not closed after use
  • Below, I’ll detail each of the causes of a memory leak

5.1 collection class

  • Memory leak cause The collection element object is still referenced by the collection class after the collection element is added. As a result, the collection element object cannot be reclaimed, resulting in a memory leak

  • Examples demonstrate

List List<Object> objectList = new ArrayList<>(); for (int i = 0; i < 10; i++) { Object o = new Object(); objectList.add(o); o = null; } // The collection element reference itself is freed: o=null) // But the collection List still refers to the object, so the garbage collector still cannot collect the objectCopy the code
  • After a collection element object is added to the solution collection class, it must be removed from the collection after use

Since there are many elements in a collection, the simplest method = empty the collection object & set to NULL

// Release objectList objectlist.clear (); objectList=null;Copy the code

5.2 Member variables modified by the Static keyword

  • The lifetime of a member variable decorated with the Static keyword = the lifetime of the application

  • Leak reason If made by the Static keyword modified member variables refer to expend resources too many instances, such as Context, is prone to life cycle of the member variable > reference instance lifecycle, when to end life cycle destroyed by examples, by Static variables hold and can’t be recycled, thus appeared memory leaks

  • Instance to explain

Public class class name {// Define a static variable private static Context mContext; / /... // Reference the Activity's context mContext = context; // When an Activity needs to be destroyed, the Activity cannot be reclaimed because mContext = static & lifecycle = the life cycle of the application, resulting in a memory leak.Copy the code
  • The solution
  1. Try to avoidStaticMember variables refer to instances that are too resource-intensive (e.gContext)

If Context is referenced, use Applicaiton’s Context as much as possible

  1. Using weak References(WeakReference)Hold instances instead of strong references

Note: A very typical example of a static member variable is the singleton pattern

  • Because of its static nature, the lifetime length of the stored knowledge singleton pattern is equal to the lifetime of the application

  • Leak cause If an object is no longer needed and a singleton still holds a reference to that object, the object cannot be recycled properly, resulting in a memory leak

  • Examples demonstrate

// Since the singleton holds a reference to the Activity (until the end of the application lifecycle), even if the Activity exits, The Activity's memory is not reclaimed, especially for large activities. OOM public class SingleInstanceClass {private static SingleInstanceClass; private Context mContext; private SingleInstanceClass(Context context) { this.mContext = context; Public SingleInstanceClass getInstance(Context Context) {if (instance == null) {instance = new SingleInstanceClass(context); } return instance; }}Copy the code
  • The lifecycle of the object referenced by the solution singleton pattern = the lifecycle of the application

In the example above, the Application Context should be passed, since the Application lifecycle = the entire Application lifecycle

public class SingleInstanceClass { private static SingleInstanceClass instance; private Context mContext; private SingleInstanceClass(Context context) { this.mContext = context.getApplicationContext(); Public SingleInstanceClass getInstance(Context Context) {if (instance == null) {instance  = new SingleInstanceClass(context); } return instance; }}Copy the code

5.3 Non-static inner Classes/Anonymous Classes

  • Non-static inner/anonymous classes hold references to external classes by default; Static inner classes do not
  • Common situation

    3, respectively: instances of non-static inner classes = static, multithreading, messaging mechanism (Handler)

5.3.1 Instances of non-static inner classes = static

  • If the instance created by a non-static internal class is static (its life cycle is equal to the life cycle of the application), the external class cannot be released because the non-static internal class has references to the external class by default, resulting in memory leakage

That is, a static object in an external class that holds a non-static inner class

  • Examples demonstrate
// Background: a. When an Activity is started frequently, a singleton of a non-static inner class is created inside the Activity to avoid creating the same data resource repeatedly. Public class TestActivity extends AppCompatActivity {// A reference to an instance of a non-static inner class // Note: Set it to static public static InnerClass InnerClass = null; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); If (innerClass == null) innerClass = new innerClass (); } private class InnerClass {//... The innerClass life of a singleton of a non-static innerClass = the life of the App that holds a reference to the external class TestActivity // b. TestActivity cannot be collected by GC, resulting in a memory leakCopy the code
  • The solution
    1. Set non-static inner classes to: static inner classes (static inner classes do not hold references to external classes by default)
    2. The inner class is extracted and encapsulated as a singleton
    3. Try to avoid instances created by non-static inner classes that = static

To use Context, you are advised to use the Application Context

5.3.2 Multithreading: AsyncTask, implement Runnable interface, inherit Thread class

  • Multithreading = non-static inner class/anonymous class; That is, the thread class is a non-static inner class/anonymous class
  • When a worker thread is working on a task & an external class needs to be destroyed, the worker thread instance holds a reference to the external class, making it impossible for the external class to be collected by the garbage collector (GC), resulting in a memory leak
  1. Multithreading mainly uses:AsyncTask, implementation,RunnableInterface & InheritanceThreadclass
  2. The principle of the first three is the same as that of memory leakage, which is mainly inherited hereThreadClass as an example
  • Examples demonstrate
/** * mode 1: New Thread subclass (inner class) */ public class MainActivity extends appactivity {public static final String TAG = "Carson: "; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); New MyThread().start(); Private class MyThread extends Thread{@override public void run() {try {thread.sleep (5000); Log.d(TAG, "multithreaded "); } catch (InterruptedException e) { e.printStackTrace(); }}}} /** * Mode 2: Public class MainActivity extends AppCompatActivity {public static final String TAG = "Carson: "; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); New Thread() {@override public void run() {try {thread.sleep (5000); Log.d(TAG, "multithreaded "); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); }} /** * */ / The Thread class belongs to a non-static inner class/anonymous inner class. The runtime holds references to external classes by default. Will make external classes unable to be collected by the garbage collector (GC), resulting in a memory leakCopy the code
  • As you can see from the above, there are two key conditions that can cause memory leaks:
  1. A worker thread instance holds a reference to an external class
  2. Life cycle of the worker thread instance > life cycle of the external class, that is, the worker thread is still running and the external class needs to be destroyed

Solution idea = make any condition 1 above not true.

// There are two solutions: static inner class & force the thread to terminate when the outer class terminates // Static inner classes do not hold references to external classes by default, thus eliminating the "worker thread instance holds references to external classes" reference relationship. Public class MainActivity extends AppCompatActivity {public static final String TAG = "Carson: Compatactivity. "; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); New MyThread().start(); } // Analysis 1: custom Thread subclass // set to: Private static class MyThread extends Thread{@override public void run() {try {thread.sleep (5000); Log.d(TAG, "multithreaded "); } catch (InterruptedException e) { e.printStackTrace(); }}}} /** * Solution 2: Force thread termination when an external class terminates its life cycle * Principle: Synchronize the life cycle of a worker thread instance with the life cycle of an external class * Implementation: When the external class (in this case, Activity) ends its life cycle (onDestroy () is called), */ @override protected void onDestroy() {super.ondestroy (); Thread.stop(); // Force the thread to terminate at the end of the Activity life cycle}Copy the code

5.3.3 Message Passing Mechanism: Handler

Android memory leak: Handler memory leak causes

5.4 The Resource Object is Not Closed After Being Used

  • If resources (such as broadcast BraodcastReceiver, File stream File, database Cursor, and image resource Bitmap) are not closed or unregistered when the Activity is destroyed, they will not be reclaimed, resulting in memory leakage

  • The solution closes/unlogs the resource when the Activity is destroyed

// For broadcast BraodcastReceiver: unregisterReceiver() // For File stream File: InputStream/outputstream.close () // For database cursor: close cursor after use // For image resource Bitmap: Android allocates only 8M memory for images. If a Bitmap takes up a lot of memory, it calls recycle() to reclaim the memory occupied by pixels of this object when it is no longer in use. Finally, assign to null bitmap.recycle (); Bitmap = null; // For animation (property animation) // Set animation to repeatCount = "infinite" after // Remember to stop animation when Activity exitsCopy the code

5.5 Other Uses

  • In addition to the four common situations mentioned above, there are some everyday uses that can cause memory leaks
  • Mainly include:Context,WebView,Adapter, detailed introduction is as follows


Schematic diagram

5.6 summarize

Below, I’ll summarize the causes of memory leaks in Android with a graph & the solution


Schematic diagram


6. Tools to help analyze memory leaks

  • Even if the cause of memory leaks is fully understood, memory leaks will inevitably occur
  • The following will briefly introduce several mainstream tools for analyzing memory leaks, respectively
    1. MAT(Memory Analysis Tools)
    2. Heap Viewer
    3. Allocation Tracker
    4. Memory Monitor for Android Studio
    5. LeakCanary

6.1 MAT (Memory Analysis Tools)

  • Definition: aEclipsetheJava HeapMemory analysis Tool ->>Download address
  • Function: View the current memory usage

By analyzing the Memory snapshot HPROF analysis of a Java process, you can quickly calculate the size of objects in memory and see which objects cannot be collected by the garbage collector & visually view the objects that might cause this result

  • Specific usage: MAT usage guide

6.2 Heap Viewer

  • Definition: oneJava HeapMemory analysis tool
  • Function: View the current memory snapshot

You can view the proportion of each type of data in the total heap memory

  • Specific usage: Heap Viewer usage guide

6.3 Allocation Tracker

  • Introduction: a memory trace analysis tool
  • Purpose: Trace memory allocation information in order
  • Specific usage: Allocation Tracker Usage Guide

6.4 the Memory Monitor

  • A graphical memory detection tool that comes with Android Studio

  • Purpose: Tracks system/application memory usage. The core functions are as follows


    Schematic diagram

  • Specific usage: Android Studio Memory Monitor usage guide

6.5 LeakCanary

  • Profile: ONEsquareAndroidOpen source library – > >Download address
  • Function: Detects memory leaks
  • The specific use: www.liaohuqiu.net/cn/posts/le…

7. To summarize

  • This article comprehensively introduces the nature, causes and solutions of memory leaks. We hope that you can avoid memory leaks when developing

  • In the next article, I will cover performance optimization for Android. If you are interested, please stay tuned for Carson_Ho’s Android development notes


Thumb up, please! Because your encouragement is the biggest power that I write!

The Android event distribution mechanism is the most comprehensive and easy to understand solution for Android screen adaptation. It is the most comprehensive and easy to understand solution for Android screen adaptation. Android development: JSON introduction and the most comprehensive analysis method! BroadcastReceiver Is the most comprehensive version of Android’s BroadcastReceiver


Welcome to attentionCarson_HoJane books!

Share the dry things about Android development from time to time, the pursuit of short, flat, fast, but there is no lack of depth.