[Eclipse MAT] Advanced use of Eclipse Memory Analyzer Tool

Preface

Although the Java virtual machine can help us reclaim the memory, it reclaims objects that the Java virtual machine no longer references. Many times we use the system's IO stream. If the Cursor and Receiver are not released in time, it will cause memory leaks. These scenarios are common and can be avoided by general developers. However, many times the phenomenon of memory leaks is not very obvious, such as internal classes, memory leaks caused by the use of Handler, or you use some references from third-party libraries, which consume resources, but it does not cause you like system resources. Pay enough attention to release them manually. When the code becomes more and more, if the structure is not very clear, even common resources may be omitted, resulting in memory leaks. Memory leaks are likely to cause memory overflow, which is commonly referred to as OOM, which can cause application crashes and give users a bad experience. This article is to introduce the memory analysis tool MAT and actual combat to help you better analyze memory problems. The previous is the introduction of related concepts, and finally through the memory leak analysis, collection usage rate, Hash performance analysis, OQL quick reading positioning empty collection actual combat demonstration how to use MAT in practical applications. (Through some static detection, some memory leaks can also be found during the development period. There will be some static detection articles later)

A related concept

How does the Java virtual machine determine the memory leak? Here are some related concepts

1.1 GC Root

The JAVA virtual machine judges whether an object is alive through Reachability. The basic idea is to search downwards with the object of "GC Roots" as the starting point. The path formed by the search is called the reference chain. When an object reaches GC Roots, there is nothing The reference chain is connected (that is, unreachable), the object is judged to be an object that can be recycled, otherwise it cannot be recycled.

GC Roots can be any of the following objects

  • An object (such as method parameters and local variables) on the call stack of the current thread
  • The thread itself or the class loaded by the system class loader
  • Active objects reserved by native code

1.2 Memory leak

The object is useless, but it is still reachable (unreleased), and the garbage collector cannot reclaim it.

1.3 Strong (strong), soft (soft), weak (weak), phantom (phantom) references

Strong references
ordinary java references, we usually new objects are:

StringBuffer buffer = new StringBuffer();

If an object is reachable through a chain of strong references, then it will not be garbage collected. You definitely don't want the references you are using to be collected by the garbage collector. However, the objects in the collection should be removed when not in use, otherwise it will take up more memory and cause memory leaks.

Soft reference
When the object is reachable by Soft reference, gc will apply for more memory from the system instead of directly reclaiming it, and reclaiming it only when the memory is insufficient. So Soft reference is suitable for building some caching systems, such as image caching.

Weak Reference
Weak Reference does not force objects to be stored in memory. It has a relatively short life cycle, allowing you to use the capabilities of the garbage collector to weigh the reachability of an object. When the garbage collector scans the memory area under its jurisdiction, once gc finds that the object is reachable by weakReference, it will put it in the ReferenceQueue and wait for the next gc to reclaim it.

WeakReference<Widget> weakWidget = new WeakReference<Widget>(widget);

The system provides us with WeakHashMap (under the java.util package), which is similar to HashMap, except that its key uses weak reference. If a key of WeakHashMap is reclaimed by the garbage collector, the entity will also be removed automatically.

Since WeakReference is more likely to be recycled by GC, you need to use weakObj.get() to determine whether the target object reference has been recycled before using it.

Reference queque
Once WeakReference.get() returns null, the object it points to will be garbage collected, then the WeakReference object is useless, which means you should do some cleanup. For example, in WeakHashMap, the recovered keys should be deleted from the Map to avoid the continuous growth of useless weakReference.
ReferenceQueue allows you to easily track dead references. The constructor of the WeakReference class has a ReferenceQueue parameter. When the pointed object is garbage collected, the WeakReference object will be placed in the ReferenceQueue. In this way, all the recovered WeakReferences can be obtained by traversing the ReferenceQueue.

Phantom reference
is quite different from soft and weak reference. Its get() method always returns null. This means that you can only use PhantomReference itself, but not the object it points to. When the object pointed to by WeakReference becomes weakly reachable, it will be placed in the ReferenceQueue immediately, which happens before finalization and garbage collection. In theory, you can "resurrect" the object in the finalize() method (just make a strong reference point to it, and gc will not reclaim it). But the object pointed to by PhantomReference cannot be resurrected. The PhantomReference was put into the ReferenceQueue after the garbage collection and could not be resurrected.

For more discussion about Phantom reference, please refer to: understanding-weak-references

Two MAT related views and concepts

2.1 Shallow Heap

Shallow size is the size of the memory occupied by the object itself, excluding the memory of the object referenced by it, and has little effect in actual analysis.
The ShallowSize of a regular object (not an array) is determined by the number and type of its member variables; the shallow size of an array is determined by the type of the array element (object type, basic type) and the length of the array.

Shallow Size of a String object

class String{
    public final class String {8 Bytes header
    private char value[]; 4 Bytes
    private int offset; 4 Bytes
    private int count; 4 Bytes
    private int hash = 0; 4 Bytes
…}
"Shallow size“ of a String ==24 Bytes

Object members of java are all references. The real memory is on the heap, it looks like a bunch of native byte[], char[], int[], the memory of the object itself is very small. So we can see that in the Histogram graph sorted by Shallow Heap, byte and char are ranked first and second.

2.2 Retained Heap

The retained heap value is calculated by adding the sizes of all objects in the retained set. In other words, because X is released, the heap size occupied by all other released objects (including those released recursively).

Retained Set
The collection of objects that will be reclaimed by the GC when X is reclaimed.

For example:
an ArrayList holds 100,000 objects, and each occupies 16 bytes. Removing these ArrayLists can release 16 x 100,000 + X, where X represents the shallow size of the ArrayList. Compared with the shallow heap, RetainedHeap can more accurately reflect the actual size of an object (because if the object is released, the retained heap can be released).

2.3 Histogram

The number of instances of each class can be listed. Supports regular expression search, and can also calculate the retained size of all objects of this type

2.4 Dominator Tree

Dominator Tree: Dominator relationship tree between objects. If all paths from the GC root to Y pass through X, then we call X dominates Y, or X is the Dominator of Y. Dominator Tree is calculated from the complex object graph in the system. From the dominator tree of MAT, you can see the object occupying the most memory and the dominator of each object.
We can also right-click and select "Immediate Dominator" to view the dominator of an object.

2.5 Path to GC Roots

View the reference chain of an object to RC Roots.
Usually when investigating memory leaks, we will choose to exclude all phantom/weak/soft etc.references, which
means to check the reference chain that excludes phantom/weak/soft references, etc., because it is phantom/weak/soft Objects can be recycled directly by GC. What we need to see is whether an object still has a Strong reference chain (you need to manually start GC to ensure that before exporting HeapDump). If there is, it means that there is a memory leak, and then check the specific reference. .

View all references and referenced objects of the current Object:

List objects with (viewed by Dominator Tree)

incoming references refer to the object of the object,
outcoming references refer to the object of the object

Show objects by class (view by class)

incoming references refer to the object of the object,
outcoming references refer to the object of the object

2.6 OQL(Object Query Language)

Similar to SQL query language
Classes: Table
Objects: Rows
Fileds: Cols

select * from com.example.mat.Listener

Find ArrayList with size=0 and unused

select * from java.util.ArrayList where size=0 and modCount=0

Find all activities

select * from instanceof android.app.Activity

2.7 Memory snapshot comparison

Method 1: Compare To Another Heap Dump

Compare directly

Method 2: Compare Baseket

The second method is very comprehensive, you can directly give the percentage, and there are more comparison options

A real example in the development process of a colleague was introduced. Through AS's Memory monitoring, he found that the memory suddenly surged after the WeChat payment was completed. Later, compared with Compare Baseket, he found that the memory increased by 8M, and passed The tool checked the original image of bitmap (how to view the original image of Bitmap, please refer to Gao Jianwu's article: Open the original image of Bitmap in MAT ). It was found that a background image on the WeChat callback page occupies a lot of memory.

Three MAT memory analysis actual combat

Actual combat one memory leak analysis

About how to install and export the HeapDump file @高建武 has already written, here is not too long, please move:
Android memory optimization MAT introduction to
Android memory optimization MAT use advanced
The point here is to manually start once before exporting the prof file GC, this ensures that only memory snapshots of objects that cannot be recycled are saved , and Android Studio provides automatic conversion.

Find the class that caused the memory leak

Now that the environment has been set up and the heap dump has been successfully dumped, let’s analyze the problem.

method one:

  • 1. Find the target class
    If your goal is very clear during the development process, such as finding the Activity you are responsible for, then you can quickly locate
    OQL through the package name or class filter, OQL search :
    click the OQL icon, and enter select in the window * from instanceof android.app.Activity and press Ctrl + F5 (or! button) to execute
  • 2. Paths to GC Roots: exclude all phantom/weak/soft etc.references to
    check whether there is a reference chain from an object to GC Roots. It is necessary to exclude phantom references/weak references/soft references, etc., because objects that are phantom references/weak references/soft references can be directly recycled by the GC.
  • 3. Analyze why the specific reference has not been released and repair it

Tips:

  • When the purpose is not clear, you can directly locate the largest Object in RetainedHeap, Select incoming references, view the reference chain, locate the suspicious object, and then Path to GC Roots to analyze the reference chain
  • If you can't see the difference when you filter large objects, you can try grouping by class, and then look for suspicious objects for GC reference chain analysis
  • Directly view the GC reference chain according to the package name, you can filter multiple classes at once, but as shown in the figure below, the option is Merge Shortest Path to GCRoots. This option is not very clear, but it can also filter out the classes that have the GC reference chain. The accuracy of this method has yet to be verified.

So sometimes some experience is needed for MAT analysis, which can help you locate faster and more accurately.

Analysis of the utilization rate of the second set of actual combat

The collection is often used in development, how to choose a suitable data structure collection, what is the initial capacity (too small, may lead to frequent expansion), too large, and it will cost more memory. When these problems are not very clear or you want to check the usage of the collection, you can analyze it through MAT.

1. Screen the target audience

2. Show Retained Set (find the collection of objects that will be recycled by the GC when X is recycled)

3. Filter the specified Object (Hash Map, ArrayList) and group by size

4. View the Immediate dominators of the specified class

Collections fill ratio

In this way, only those collections with pre-allocated memory capabilities can be viewed, such as HashMap and ArrayList. Calculation method: "size / capacity"

Actual Combat Three Hash Related Performance Analysis

When too many objects in the Hash collection return the same Hash value, it will seriously affect the performance (the principle of the Hash algorithm searches on its own), here to find the culprit that causes the high collision rate of the Hash collection.

1. Map Collision Ratio

Detect each HashMap or HashTable instance and sort according to the collision rate.
Collision rate = collision entities/all entities in the Hash table

2. View Immediate dominators

View key value through HashEntries

Array and other collection analysis methods are similar

Actual combat four quickly locate unused collections through OQL

1. Query the empty and unmodified collection through OQL:

select * from java.util.ArrayList where size=0 and modCount=0

akin

select * from java.util.HashMap where size=0 and modCount=0
select * from java.util.Hashtable where count=0 and modCount=0

 

2. Immediate dominators (see referer)

Calculate the Retained Size value of the empty collection to see how much memory was wasted

Four LeakCanary-a powerful memory leak analysis tool

LeakCanary is a square open source memory leak investigation project. It is very powerful. It will help you manually trigger the GC and then analyze the strong reference GC reference chain. If there is a GC reference chain, it means there is a memory leak, a prompt box will pop up on your phone, and an App will be automatically created on your phone. The GC reference chain of each memory leak is recorded, and the unreleased object of the memory leak can be directly located through it. The principle is the same as analyzing memory leaks through MAT, except that it is fully automated and saves a large part of the workload. It is strongly recommended to integrate LeakCanary. LeakCanary certainly cannot replace the powerful MAT, because it only analyzes memory leaks. From the actual combat above, we can see that the power of MAT is that it can analyze any information in the memory. Therefore, it is very necessary to master MAT. In addition, in the LeakCanary used before, it was found that there will be problems when parsing the Heap Dump memory snapshot, and there are small bugs.

Reference documents

Main reference: https://blog.csdn.net/coslay/article/details/48182709

Wiki MemoryAnalyzer
Android memory optimization MAT Getting Started with
Android memory optimization MAT using advanced
10-Tips-for-a using-at The Analyzer-the Eclipse-Memory-
ANALYZING-the Java-the Collections-with-Memory-Usage Analyzer-
How-to-the Find-Memory -Leaks
How_to_analyze_heap_dumps
memory-for-nothing

Reprinted from: Advanced Use of MAT-Memory Analyzer Tool

Guess you like

Origin blog.csdn.net/xiaoxiao_su123/article/details/113240399