preface
- in
Android
Memory 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
1. Introduction
- namely
ML (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.e
OOM
Introduction to memory overflow:
3. The root cause of memory leakage
- A detailed description
- Special attention has been paid to the fact that, from an institutional point of view
Java
Garbage 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
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 Framework
Determines the type of process to recycleProcesses 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:
- Step 2:
Linux
The kernel actually recycles specific processesActivityManagerService
All processes are scored (scores are stored in variablesadj
C)- Update score to
Linux
The kernel - by
Linux
The kernel does true memory reclamation
Here only summarizes the process, the process of the complex, interested readers can research system source ActivityManagerService. Java
4.3 Memory Policies for objects and variables
Android
The 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
Note: Use an example to explain memory allocation
public class Sample { int s1 = 0; Sample mSample1 = new Sample(); Public void s1, mSample1 public void s1, mSample2 public void s1, mSample1 public void s1, mSample2method() { int s2 = 0; Sample mSample2 = new Sample(); MSample3 = new Sample(); mSample3 = new Sample();Copy the code
B. Memory release policy
- Object/variable memory freed by
Java
Garbage collector (GC
)/frame stack is responsible - The focus here is on the memory free strategy of object allocation (heap allocation) =
Java
Garbage 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
Java
Garbage collector (GC
) = garbage collection algorithm, mainly including:
- The details are as follows
5. Common Causes of memory leaks & Solutions
- Common causes of memory leaks are as follows:
- Collection classes
Static
The keyword modifies the member variable- Non-static inner class/anonymous class
- 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
- Try to avoid
Static
Member variables refer to instances that are too resource-intensive (e.gContext
)
If Context is referenced, use Applicaiton’s Context as much as possible
- 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) {public SingleInstanceClass getInstance(context context) {if (instance == null) {
instance = new SingleInstanceClass(context);
}
returninstance; }}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);
}
returninstance; }}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
- There are 3 common cases, which are: instances of non-static inner classes = static, multithreading, message passing 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); // Ensure that there is only one instance of a non-static inner classif(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
- Set non-static inner classes to: static inner classes (static inner classes do not hold references to external classes by default)
- The inner class is extracted and encapsulated as a singleton
- 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
- Multithreading mainly uses:
AsyncTask
, implementation,Runnable
Interface & InheritanceThread
class- The principle of the first three is the same as that of memory leakage, which is mainly inherited here
Thread
Class as an example
- Examples demonstrate
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 Overriderun() {
try {
Thread.sleep(5000);
Log.d(TAG, "Performed multithreading."); } catch (InterruptedException e) { e.printStackTrace(); }}}} /** * Mode 2: anonymous Thread internal class */ 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); // Implement multithreaded new through anonymous inner classesThread() {
@Override
public void run() {
try {
Thread.sleep(5000);
Log.d(TAG, "Performed multithreading."); } 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:
- A worker thread instance holds a reference to an external class
- 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. Make Thread subclasses static inner classes */ 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 MyThread().start(); } // Analysis 1: Custom Thread subclass // Set to: private static class MyThread extends Thread{@override public voidrun() {
try {
Thread.sleep(5000);
Log.d(TAG, "Performed multithreading."); } 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: Force the thread to terminate (stop ()) */ @override protected void when the external class (in this case, the Activity) ends its life cycle (onDestroy () is called)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
5.6 summarize
Below, I’ll summarize the causes of memory leaks in Android with a graph & the solution
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
MAT(Memory Analysis Tools)
Heap Viewer
Allocation Tracker
Memory Monitor for Android Studio
LeakCanary
6.1 MAT (Memory Analysis Tools)
- Definition: a
Eclipse
theJava Heap
Memory 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: one
Java Heap
Memory 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
-
Specific usage: Android Studio Memory Monitor usage guide
6.5 LeakCanary
- Profile: ONE
square
‘Android
Open 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
-
The next article I will explain the Android performance optimization related knowledge, interested students can continue to follow my rare earth digging home page oh