### Give a memory leak chestnut first
We often create utility classes in projects, such as those for getting screen information, SharePreference, image compression, and so on, and we tend to write them in simple terms, as shown in CommonUtils below. (Application Context should be used to prevent memory leaks.)
Public class CommonUtils {private static CommonUtils sInstance; private Context mContext; private CommonUtils(Context context) { mContext = context; } public static CommonUtils getInstance(Context context) { if (sInstance == null) { sInstance = new CommonUtils(context); } return sInstance; }}Copy the code
In activities, we often use this:
public class LeakActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_leak); CommonUtils.getInstance(this); }}Copy the code
This is a typical singleton pattern that results in an Activity memory leak because the CommonUtils holds a reference to the Activity, so the Activity cannot be recycled properly. That is, it exists after Destroy.
Let’s start with a simple example of how to use the tool, and then summarize how we can use the clues provided by the tool to analyze when we don’t know where a memory leak is occurring.
###Android Studio Android Monitor
Run our project first, then open the Android Monitor. As shown below:
The Android Monitor can see some information about the phone, and we are most concerned about the Memory section. Here you can see the free memory and allocated memory of our APP process, as shown on the right. In the earlier part of the figure, we can see that the allocated memory is suddenly reduced, which is the GC collecting garbage.
###### memory jitter: when memory fluctuates very frequently, this is memory jitter. At this time, it is necessary to pay attention to whether memory leaks are caused.
There are three widgets in the upper left corner, the first two are introduced here, the first is to manually trigger the GC and the second is to take a heap memory snapshot.
We manually trigger the GC a few more times, wait until memory stabilizes, and then take a snapshot, at which point the AS will automatically pull the HPRF file and open it. We then rotate the screen, triggering a memory leak, and repeat the process again.
We can choose to view the memory information of APP, Image and Zygote, or choose to display it by package name. The following parameters need to be explained: The unit is byte
Total Count: indicates the Total number of objects. Heap Count: The number of objects in the Heap memory. Sizeof: the Sizeof the object itself. Shallow Size: Total Size of all objects of this class. Retained Size: The total memory freed when all the objects of this class (including the objects that reference this class) are released. Depth: Depth at which the object is referenced. If it is not, the Depth is 0. Direct reference, depth 1, and so on. Dominating Size: memory Size governed by the object.
Now let’s analyze it and show it according to the package name to find our LeakActivity. You can see several LeakActivity instances on the right. We can see the reference tree for LeakActivity below. Note that our CommonUtils reference LeakActivity directly via mContext, which is highlighted in blue to indicate a memory leak. We can also do automatic analysis by clicking on the green triangle in the upper right corner of Analyzer Tasks on the right.
In fact, we can predict whether there is a memory leak by looking at the number of activities (2).
###### if we rotate it a few more times, there will be multiple instances of the Activity in memory, but if memory gets tight, only the 0th and last instance will be kept. The activities in the middle are recycled because they are not referenced by CommonUtil.
CommonUtil and Activity lifecycles are inconsistent, which can cause leaks.
The actual project is more complex, need to reference tree one by one analysis, reference is reasonable, and then look at the code. Tools are just clues.
The use of the # # # MAT
MAT is short for Memory Analyzer Tools. It is a dedicated Java Memory Analyzer tool. MAT is a plug-in for Eclipse.
First we need to convert the Hprof file generated by AS into a standard file, of course, if it is ADT, it can be used directly. As shown below:
Then open it in MAT: we generally select the memory leak analysis report.
You can see some problems reported here, such as the Resources class being loaded by the system’s classloader and taking up a lot of memory. But in general this interface is useless.
The following interface is important:
Histogram: Lists number of instances per class Number and size of objects in memory.
Dominator Tree: List the biggest objects and what they keep alive. Enumerates large objects, what they depend on, and whether they still exist.
This interface allows you to see things similar to AS, which I won’t go into here.
Let’s review the GC collection algorithm first: the object of “GC Roots” is used as the starting point to search down, and the path formed by the search is called the reference chain. When an object is not connected to GC Roots by any reference chain (that is, unreachable), the object is judged to be recyclable, otherwise it cannot be recycled. It also writes out the cause of the memory leak: the object is useless, but still reachable (unfreed) and cannot be collected by the garbage collector. Objects that reference each other and cannot be reclaimed are memory leaking objects.
We searched LeakActivity and right click to Merge Shortest Path to GC Roots Select Exclude all phantom/weak/soft etc. References to see references that exclude virtual /weak/soft references, etc. (all references will eventually be eliminated by GC, so exclude). Finally, you can see that there are two more objects that reference LeakActivity, where the input method is a BUG in the system.
You can also see who the object is referenced by, or referenced by, incmming outcomming
###### Snapshot comparison When we suspect that the APP is slow due to the execution of an action, we can take a snapshot before the action, and then take another one after the action, and then use MAT for comparison.
In the Navigation History interface, select History Add to Compare Basket and click the red exclamation mark in the upper right corner to perform comparison analysis. Through comparison analysis, problems can also be found by looking at the memory allocation and quantity difference of objects before and after the operation.
Finally, we can also predict the number of views and activities directly from the Android Monitor memory report: When the app exits, all objects in the process should be reclaimed, especially those that are vulnerable to leaks. After the app exits, check whether all View and Activity objects in the process are 0. Tools: Use AndroidStudio–AndroidMonitor–System Information–Memory Usage to check if the number of views and activities in Objects is 0.
# # #
Often when you’re working on a project it’s very complicated, or you’re almost done with the project and you want to optimize performance and check for memory leaks.
How do you find these places in your project where memory leaks exist?
1. Check whether memory leaks exist
1) Memory analysis by Android Monitors is the most intuitive way to look at memory growth and determine if the action has leaked. (Memory jitter) before action: memory 1.4m after GC; 2) Use MAT to analyze the total memory footprint of the heap to determine whether there is a leak. There is a Type called Data object in the heap view, that is, a large number of class Type objects in our program. In the Data Object line, there is a column called "Total Size", which is the Total amount of memory for all Java data objects in the current process. In general, this value determines whether there will be a memory leak. Note that the Total Size value of the data object is normally stable within a limited range. That is to say, due to the good code in the program, there is no case that the object is not garbage collected. On the contrary, if there is no object reference released in the code, the value of Total Size will increase as the number of operations increases.Copy the code
This is a preliminary indication that this operation is causing a memory leak.
2. Find suspects first (which ones are leaked)
MAT compares the hPROF before and after the operation to locate what data objects the memory leak is leaking. (Do this to exclude some objects, without later checking whether all referenced objects are suspected.) Quickly locate which objects are increased before and after the operation (after GC or more objects may be suspected of leaking objects). In Histogram, objects can also be grouped. For example, selecting Group By Package makes it more convenient to view object information in your Package.Copy the code
3.MAT analyzes HPROF to locate the cause of memory leaks. 1) Dump the memory mirror hprof of the “at the time” of the memory leak and analyze the suspected leaking classes; 2) Run through all the suspects identified in 2 above. Steps:
(1) Enter Histogram and filter out a certain suspected object class (2) Then analyze the external Objects that hold such object references (right-click List Objects- >with incoming References) (3) Filter out some weak references, soft references, and virtual references. It is not a memory leak because they can be eliminated by GC sooner or later (right click on the above class to Merge Shortest Paths to GC Roots-- >exclude all phantom/weak/soft etc. References) (4) One by one analysis of each object GC path is normal at this time will enter the code analysis at this time the object reference hold is reasonable, this will test experience and physical strength! (For example, in the class example: after rotating the screen, there are two MainActivity, which must be leaked, then who caused it to leak? It turns out that our CommonUtils class holds the MainActivity before the rotation. Is that reasonable? The CommonUtils class is holding the MainActivity instance. How to solve it? The culprit is found, how to solve it should not be difficult, different situations to solve the solution is not the same, to rely on your wisdom.Copy the code
If you feel that my words are helpful to you, welcome to pay attention to my public number:
My group welcomes everyone to come in and discuss all kinds of technical and non-technical topics. If you are interested, please add my wechat huannan88 and I will take you into our group.