Detecting multiple instances of a custom object via LeakCanary

77 views Asked by At

As per the docs, looks like LeakCanary only provides information about leaked object. But, I am also interested in finding multiple instances of certain custom HeavyWeightObject objects. Can LeakCanary help in this? If so, how?

I should mention that the problem is that we don't own the HeavyWeightObject. In fact this object could be injected from different locations. It could inadvertently be injected from a third party library as well.

I have used a heap analyzer like YourKit and the number of instances does show up there. I was wondering if tweaking something in the LeakCanary codebase can give that information as well?

1

There are 1 answers

2
VonC On

LeakCanary primarily focuses on detecting memory leaks, that is, objects that are retained in memory when they should have been garbage collected. However, it does not directly provide functionality to detect multiple instances of a custom object that are not necessarily leaked.

That means you would need a different approach: You could use a heap analysis tool like Android Studio's Profiler or Eclipse Memory Analyzer Tool (MAT). These tools allow you to inspect the heap and find instances of your classes.

You might also consider implementing a static counter or a list in your class to keep track of instances. Make sure to update this counter/list in the constructor and finalizer (or in onDestroy for Android components). That was actually considered in 2012 in this question

A manual tracking (without the need for an onDestroy method) could look like:

public class HeavyWeightObject {
    private static final List<WeakReference<HeavyWeightObject>> instances = new ArrayList<>();

    public HeavyWeightObject() {
        instances.add(new WeakReference<>(this));
    }

    public static void checkInstances() {
        // Remove cleared references
        instances.removeIf(ref -> ref.get() == null);

        // Check the number of instances
        if (instances.size() > SOME_THRESHOLD) {
            // Handle multiple instances case
        }
    }
}

The instances list holds weak references (WeakReference<HeavyWeightObject>) to instances of the HeavyWeightObject. Weak references allow the garbage collector to reclaim the referenced objects when they are no longer in use. That means that even if an object is still referenced in the instances list, it does not prevent the object from being garbage collected.
See also "Android weakReference to Activity goes null while activity is executing"

Periodically call HeavyWeightObject.checkInstances() to monitor the number of instances. In an activity or fragment, you might choose to add or remove references in lifecycle methods like onCreate and onDestroy

That method would help to get the number of instances of your object at a given time, which can be useful to identify patterns or scenarios where multiple instances are being created inadvertently.


I should have mentioned (added to the question now) that the problem is that we don't own the HeavyWeightObject. In fact, this object could be injected from different locations. It could inadvertently be injected from a third-party library as well.
So, using WeakReferences this way would not work.
I have used a heap analyzer like YourKit and the number of instances does show up there. I was wondering if tweaking something in the LeakCanary codebase can provide that information as well?

Given that you do not own the HeavyWeightObject and it could be injected from various sources, including third-party libraries, manual tracking using weak references is not a feasible approach indeed.

LeakCanary is designed for detecting memory leaks by analyzing heap dumps. The process involves identifying objects that are retained (i.e., not garbage collected when they should be) and then tracing back to find what is holding references to them.

LeakCanary uses Shark (Heap Analysis Library) for analyzing heap dumps. You can potentially modify or extend this analysis to count instances of HeavyWeightObject. That would involve parsing the .hprof heap dump file and counting occurrences of the class.

So... in theory, you could fork leakcanary/shark/, and implement custom logic in LeakCanary's heap analysis process to specifically look for instances of HeavyWeightObject. That logic could be similar to how LeakCanary identifies leaking objects, but instead of looking for leaks, it would count the instances of the specified class.