Profiler for Android memory leak detection

Speaking of Android memory leaks, many people subconsciously think: LeakCanary   , import dependencies, and directly look at the results of the notification bar after running.

But, have you ever thought that LeakCanary    checks the scope of memory leaks? In fact, LeakCanary    can and can only detect Activity memory leaks

Focus: LeakCanary can only detect Activity memory leaks

why?

[ Principle of LeakCanary ]

Because LeakCanary  monitors the creation and destruction of the entire application's Activity through  ActivityLifecycleCallbacks  . When an Activity is destroyed,

Just assign a weak reference to this Activity, and then manually GC to prompt the garbage collector to collect garbage. Then check in the garbage queue to see if there is the Activity that was just destroyed,

If not, it means that the Activity has leaked.

 

This design traces a lot of source code, as well as the mechanism of the Java garbage collector, which is not explained in detail here. My previous blog talked about the garbage collection mechanism. You can see.

But here comes the problem, what if I am not Activity leaking? Is it a Fragment leak? Is an entity object leaked? How to detect it?

This LeakCanary   is not detectable. . . . . . So, another tool is needed at this time,

 

Hum! ! ! ! ! ! Profiler is out. Android studio comes with tools.

In particular, each version of the Profiler style is different, this post is based on Android studio3.4

 

[ 1: Where is the Profiler? 

After running the project, you can see the Profiler in the bottom bar

 

2: How to use Profiler? 

Well, our application is up and running. We click on the Profiler and see the effect

You can see that there are three indexes in the Profiler column, CPU, MEMORY, and NETWORK, which respectively refer to: CPU usage, memory usage and network status

Now we are going to analyze the memory. So we click MEMORY, it will show the memory usage separately, as follows:

This interface is the memory status when the application is running. Just look at the screenshot. .

There are generally two ways to analyze memory through Profiler.

[ Analyze memory method one  , enter and exit pages, force manual triggering of GC, Dump Heap analysis ]

Okay, let's first construct a page that will leak memory, such as:

class LeakActivity : AppCompatActivity() {

    companion object {
        fun launch(context: Context) {
            context.startActivity<LeakActivity>()
        }

        lateinit var leakActivity: LeakActivity
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_leak)
        leakActivity = this
    }
}

The static variable refers to the current Activity.

Then our steps are:

1>Enter the currently leaked page, then exit

2> Manually click the trash can button to trigger the GC and trigger the collection of garbage objects. (This ensures that the objects that need to be recycled are not in memory)

3> After 3 seconds to download and click the heap heap memory data, (why after 3 seconds? Because the garbage collector has enough time to recycle all the objects that need to be recycled)

4>After waiting a few seconds, Android studio will automatically generate heap memory data. For example, the following screenshot:

Will generate such a memory data analysis graph. As long as it is in this analysis directory, it means the memory data collected by the garbage collector. If your object should disappear in memory, but it appears in this directory, it means that your object cannot be recycled by the garbage collector and leaked.

For this directory, choose to display data according to our package name directory.

For example, the package name of my current application is: com.leo.dicaprio.myutilapp and  we will expand the com directory to find it.

Other directories may be systems or some other modules, we basically do not need to analyze. We only need to analyze whether our application is leaked.

Then, from the code above, we suspect that LeakActivity is leaking because it is referenced by static variables from the code.

So we have been looking for this LeakActivity package path to see if it is still in memory? Look at the screenshot

Sure enough, he was still in memory. Not recovered, leaked. We double click on a leaked LeakActivity,

He will pop up the instance View, and then click on LeakActivity inside, and you will see the Reference window,

The Reference list is a list of all references to LeakActivity, we need to find out which reference causes LeakActivity to be unable to be recycled.

Here, the previous wave:

I saw it. A variable named leakActivity (see the case clearly), references LeakActivity (see the case clearly),

Then continue to click and find that the leakActivity variable is in LeakActivity. This is very clear. . . .

Here to talk about, there are four parameters on the right side of heap Dump, specifically:

Alloc Count: the number of instances in the Java heap
Native Size: the memory size allocated by the native layer.
Shallow Size: The actual size allocated in the Java heap.
Retained Size: The total size of the memory reserved by all instances of this class (not the actual size)

 

[ Analysis of memory method two, enter and exit pages, manually trigger GC analysis, Record analysis  ]

The first one is to manually trigger gc, and then look at the memory. But, have you noticed that there are many messy system references in the reference queue? This requires a certain degree of knowledge to find out those in the system and those in your own application.

At this time, we want to look at the second method. Well, let's come to the second analysis: memory recording. Record the state of the memory at a certain time. Then also through 

Quoting the queue to locate and analyze, but it has one advantage, what advantage? First look at the following, first construct a memory leak example:

public class Leak2Activity extends AppCompatActivity {

    public static void launch(Context context) {
        Intent intent = new Intent(context, Leak2Activity.class);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_leak2);
        postHandler();
    }

    private void postHandler() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {

            }
        },999999999);
    }
}

Then the steps are:

1: Click the record button to start recording memory

2: Enter Leak2Activity, and then exit

3: Manual GC, click the button after 3 seconds to stop recording.

4: Wait for the memory data to be generated and analyzed. . . .

which is:

[1: Click the record button to start recording memory]

[2: Enter Leak2Activity, then exit ]

Screenshot omitted here

[3: Manual GC, click the button to stop recording after 3 seconds ]

[4: Waiting to generate memory data, analysis ]

 

Look at the analysis chart, the recorded memory data analysis chart.

Still choose the package name to assign the directory

Then we see that our Leak2Activity is still in memory, indicating a leak. Then we click on Leak2Activity&1 to pop up InstanceView

Then click Leak2Activity&1 again to see Allocation Call Back, a magical scene appears,

See the method name in the Leak2Activity class. Yes, it means that these two methods in these two types are references to Leak2Activity.

Then I didn’t talk about the benefits of this method. The advantage is that it can accurately locate the method for you to refer to this class.

Then we double-click one of the method names, and Android Studio jumps directly to the code of this method.

 

Then look at the code to know why this method causes a memory leak.

[ Summary ]

So to summarize, these two methods are different:

Method 1 : Force GC, generate heap Dump, and analyze memory references.

Benefits: No need to know the object creation time, you can view the heap memory data at any time

Disadvantages: unable to locate the relevant code, too many system confusion references.

Method 2 : Record memory data, enter and exit pages, analyze memory data

Benefits: You can locate the relevant code without looking at too many system confusion references.

Disadvantages: Need to know the object creation time, which can only be viewed during the memory recording time

 

Of course, the Activity is displayed now, in fact, it can also detect whether an instance of any class leaks. The principle is the same.

 

 

 

There is no problem with the above code, please leave a message if you have any questions. Thank you!

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/Leo_Liang_jie/article/details/93871361