Android application memory leak analysis and improvement experience summary

Android application memory leak analysis and improvement experience summary

Preface

Through the memory leak detection and improvement of several applications in the past few days, the effect is obvious:

  • When the application is completely exited, GC is manually triggered, and the memory usage is reduced from more than 100M to less than 20M;
  • After manually triggering GC, the number of Activities and Views is also close to 0 when checking adb shell dumpsys meminfo packagename -d (the reason why it is not zero is that there is a memory leak in the SDK, which needs to be handled by the middle layer);
  • Found a memory leak in the SDK (Memory leak caused by Android InputMethodManager and its solution);
  • A memory leak in MTK Webview was found (memory leak caused by private static AwPasswordHandler sInstance = null in org.chromium.android_webview.AwPasswordHandler.java).

Judging from the results, my method of analyzing and improving memory leaks was correct. The process is not complicated, so I can summarize it for sharing.

in principle

For performance issues, analysis and improvement must follow the following principles:

  • Everything depends on the data, not your feelings. If you make changes just because you feel there is a problem, it is likely to backfire.
  • Performance optimization is an ongoing process that requires continuous improvement. Don’t expect to complete it all at once.
  • Performance issues do not necessarily need to be improved. Due to architectural or other reasons, some issues may be difficult to improve. You must first ensure that it can be used before considering how easy it is to use.
  • Be sure to verify after improvement. Any changes in any place need to be verified to avoid other problems caused by improving performance issues.

step

Here are the steps I took to solve the memory leak performance problem:

Prioritize common memory leak issues

First, solve the common memory leak problem. In this process, you can use Android Studio's Analyze-Inspect Code to perform static analysis on the code. Common memory leak problems include:

  • The solution to memory leaks caused by non-static inner classes, such as Handler, is to write the inner class as a static inner class and use soft references/weak references in the static inner class to hold the instance of the outer class, eg:
  1. static class ExerciseHandler extends Handler{
  2.  
  3. private SoftReference<ExerciseActivity> exerciseActivitySoftReference = null ;
  4.  
  5.   
  6.  
  7. public ExerciseHandler(ExerciseActivity exerciseActivity){
  8.  
  9. exerciseActivitySoftReference = new SoftReference<ExerciseActivity>(exerciseActivity);
  10.  
  11. }
  12.  
  13.   
  14.  
  15. @Override
  16.  
  17. public void handleMessage(Message msg) {
  18.  
  19. ExerciseActivity exerciseActivity = exerciseActivitySoftReference.get();
  20.  
  21. if( null != exerciseActivity){
  22.  
  23. super.handleMessage(msg);
  24.  
  25. switch (msg.what) {
  26.  
  27. case MSG_XX:
  28.  
  29. exerciseActivity.***;
  30.  
  31. break;
  32.  
  33. default :
  34.  
  35. break;
  36.  
  37. }
  38.  
  39. }
  40.  
  41. }
  42.  
  43. }
  • Memory leaks caused by not closing files after IO operations, such as not closing Cursor, FileInputStream, and FileOutputStream after use. This problem can be detected through static code analysis in Android Studio 2.0 and can be improved directly;
  • After using TypedArray in a custom View, there is no recycle. This problem can also be checked through static code analysis in Android Studio 2.0, and it can be improved directly;
  • In some places, the context of the four major components is used. After leaving these components, the context is still held, which causes memory leaks. This problem is a consensus. In the process of writing code, you should follow the rules and use the Application context to solve this kind of memory leak problem. As for when to use the context of the four major components and when to use the Application context, please refer to the following table:

applicationUse scenarios

Note: Please note that some numbers are added to some NOs. In fact, these are YES in terms of ability, but why are they NOs? The following explains them one by one:

1. Number 1: It is possible to start an Activity in these classes, but you need to create a new task, which is generally not recommended;

2. Number 2: It is legal to inflate layout in these classes, but the system default theme style will be used. If you customize some styles, they may not be used;

3. Number 3: Allowed when Receiver is null, used to get the current value of sticky broadcast in version 4.2 or above. (Can be ignored);

4. ContentProvider and BroadcastReceiver are in the above table because they have a context for use in their internal methods.

There is another type that does not belong to memory leaks, but should be solved when analyzing memory leaks: for the same APP, if you put pictures in different drawable folders, the memory occupied on the same device will be different. For details, please refer to: Research and Analysis on the Relationship between Picture Size, Memory Occupancy and Drawable Folders in Android. To solve this problem, just follow the following principles: 1. The UI only provides a set of high-resolution pictures. It is recommended to put the pictures in the drawable-xxhdpi folder (it is not necessary to put them in the xxxhdpi or higher resolution folders. Weigh the pros and cons and take care of mainstream devices). In this way, the size of the pictures is only compressed on low-resolution devices, and there will be no increase in memory; 2. For desktop plug-ins or pictures that do not need to be scaled, put them in the drawable-nodpi folder. The pictures in this folder will not be scaled on any device.

Use tools to check memory leaks after the program is running

Through the above steps, most memory leak problems in the application can be solved. For some memory leaks, you need to run the program and analyze the memory snapshot after running to solve them, such as not unregistering after registration, memory leaks caused by static member variables in the class, memory leaks in the SDK, etc. Solving such problems can be done in two steps:

  • Use the memory leak detection tool to locate the problem first. There are two convenient ways to detect memory leaks: 1. One is to use the open source project Leakcanary, which needs to be added to the code and run to generate analysis results; 2. The other way is to use the adb shell dumpsys meminfo packagename -d command to check the number of Activities and Views before entering an interface, and then check the number of Activities and Views again after exiting this interface, and compare the changes in the number of Activities and Views before and after entering. If there is a difference, it means that there is a memory leak (before using the command to check the number of Activities and Views, remember to manually trigger GC).

Note: In Android Studio, you can obtain the memory information of the currently selected process in the following ways:

  • Then use MAT to take a memory snapshot of the program during runtime for detailed analysis. There are many high-quality articles on the Internet about the use of MAT, such as: Android Performance Optimization Using MAT to Analyze Memory Leaks. Before using MAT, it is necessary to know the following points: 1. Don't expect MAT to tell you clearly where the memory leak is. This requires you to first locate the class that may have a memory leak according to the previous step, and then use MAT to confirm whether there is a memory leak and where the memory leak is; 2. Use Retained Size to analyze the memory consumed by a class and its related instances. If the Retained Size of this class is relatively large, give priority to analysis; 3. When checking whether a class has a memory leak, exclude its soft/weak/virtual references. Right-click a class → Merge Shortest Paths to GC Roots → exclude all phantom/weak/soft etc.references.

Verify the improvement effect

Based on my personal experience, I usually verify the improvement effect in this way: run the program, run each function once, make sure there are no problems with the changes, exit the program completely, manually trigger GC, and then use adb shell dumpsys meminfo packagename -d to check whether the number of Activivites and Views is close to 0; if it is not 0, use Leakcanary to check for possible memory leaks, continue to use MAT analysis, and repeat this cycle until you are satisfied with the improvement.

Recommended Reading

  • Speed ​​up your app
  • Android performance optimization: using MAT to analyze memory leaks

<<:  Android immersive status bar implementation

>>:  Detailed explanation of Android Bitmap cache pool usage

Recommend

Where can I check Douyin credit score? What are the rules?

Now many friends have opened accounts on Douyin. ...

How to make your Tik Tok VLOG become popular content?

Tik Tok is a short video software used by many yo...

How to write Double Eleven copy to encourage users to place orders?

When it comes to copywriting , the first thing pe...

Brand war under the epidemic

We all know that the former chairman of Coca-Cola...

10 skills you must know for e-commerce operations

It can be said that operation is the soul of a st...

1000 top landing pages, 5 conversion rate optimization tips

Conversion is the key factor in paid promotion . ...

Apple may launch web version of Apple Pay at WWDC 2016

Earlier this year, there were reports that Apple ...

10 UI/UX Lessons for Designing a Product from Scratch

[[338502]] In 2016, I realized something very imp...

4 elements to effectively increase user growth!

In the circle, whenever the word "growth&quo...