Today I will write a wave of analysis of the memory leak tool LeakCanary, and also sort out the previous notes, without further ado, source code.

I used version 1.5.1.

LeakCanary Core source code parsing

Look at the source code or that sentence, first find the entrance, follow the entrance to see the main process.

LeakCanary listens on the Activity’s onDestory method and then intervenes, so start here

Find the entry in the RefWatcher. Watch method, which is the core class, and follow the watch method.

You can see that something is going on here, so let me explain what these variables mean

This explains what happens in the watch method above

Use randomUUID to generate a random key and add it to a set. This key corresponds to the activity being monitored. This is key. Then it is packaged as KeyedWeakReference object, and KeyedWeakReference inherits WeakReference.

The next step is to operate the KeyedWeakReference weak reference.

Here we have to mention that strong weak weak weak these four things, if there are still do not understand the small partner, or to see, here only mention weak reference, in simple terms is.

When an object held by a weak reference is reclaimed, the weak reference is placed in the reference queue associated with it.

?????

Speak words! Here’s a chestnut

The watchedReference of the watch method above is held by a KeyedWeakReference weak reference. When the activity is reclaimed, RefWatcher#queue will have this KeyedWeakReference.

Conversely, if the Queue does not have the KeyedWeakReference after a session of operation, it means that the activity is not recovered, and then it is judged as a memory leak.

This is also at the heart of LeakCanary.

Okay, so the watch method goes down, and the ensureGoneAsync method goes into one of the core methods of ensureGone

The red box here is the core of the core. It looks short, but it’s concentrated.

RemoveWeaklyReachableReferences method is to traverse the reference queue in the queue in the object, in removing retainsKeys this set.

Remember what retainsKeys played at the beginning? Is the key generated by the UUID that corresponds to each activity, and can be understood as a value for the activity. When the queue has a weak reference, one of the corresponding activities has been reclaimed.

RetainsKeys = retainsKeys = retainsKeys = retainsKeys;

The whole process of ensureGone is basically clear, let’s clarify the process of ensureGone.

If DONE is returned and the process is not leaked, the gone judgment still exists, forgive ta for giving another chance, call runGc to trigger the collection, remove the key again, the gone judgment still exists, sorry, no chance. Using HeapDumper. dumpHeap out of the call chain, showNotification is displayed in the notification bar, and finally on the DisplayLeakActivity page.

Finally, the application of basic knowledge is still weak, so why does Dachang like to ask basic knowledge, in fact, a lot of things are built on basic knowledge.

Additional points about GC

Here to add something, is also before a factory asked, did not answer out, mainly before did not see so fine, and then turned over the source code.

At that time, I asked the above gc, how is the GC? When was the second removeWeaklyReachableReferences trigger?

At that time, I thought that GC is not System. Gc, also can have what SAO operation? Come back to open the source code, hey, found really have.

So GCTrigger is the place to start.

RunGc is not a direct call to system.gc, but a rung.getruntime ().gc().

Then I saw a bunch of notes on the top and posted the source URL. I felt it was very important. I calmed down and scanned it with my cet-4 English reading ability for many years.

Simply put, the author took a piece of code from AOSP with Ctrl+ C, because System.gc() does not guarantee that runtime.gc () will be more reliable each time gc is performed.

Then I called the enqueuReferences method, which directly sleep 100ms, simple and simple. It is not easy to obtain the time when the object is actually added to the queue. Therefore, it can wait 100ms for recycling. After 100ms, runFinalization can be implemented, and then the second remove can be carried out.

Good guy a class to answer two questions, the core process is finished, this time to write here, the first time with nuggets, do not know nuggets article support does not support subsequent editing, follow-up to add a wave

Thank you, friends