In our daily pursuit of building better apps, we as developers need to take many things into consideration in order to stay on track, one of which is to make sure that our apps do not crash. A common cause of crashes are memory leaks. This particular problem can manifest itself in various forms. In most cases we see a steady increase in memory usage until the app cannot allocate more resources and inevitably crashes. In Java this often results in an OutOfMemoryException being thrown. In some rare cases, leaked classes can even stick around for long enough to receive registered callbacks, causing some really strange bugs and all too often throw the notorious IllegalStateException.

To help others minimize time spent on code analysis I’ll present a few examples of memory leaks, how to identify them in Android Studio and most importantly how to remove them.

Disclaimer

The purpose of this post and its code examples is to promote a deeper understanding of memory management, especially in Java. The general architecture, management of threads and handling of running HTTP requests shown are not ideal for a production environment and merely serve as carrier of the point being made: Memory leaks in Android is a thing to be considered.

Registering listeners

This shouldn’t really be a problem but all too often I see calls to various register methods but their unregister counterparts are nowhere to be seen. This is a potential source of leaks, since these methods are clearly designed to be balanced off by each other. Without calling the unregister method, the instance will probably keep a reference around long after the referenced object has been terminated and will thus start leaking memory. In Android this is especially troublesome if that object is an activity, since they often hold a large amount of data. Let me show you what that might look like.

In this example we’re letting the Android LocationManager inform us about location updates. All we need to set this up is the system service itself and a callback to receive the updates. Here we implement the location interface in the activity itself, meaning that the LocationManager will hold a reference to our activity. Now if the device were to be rotated, a new activity would be created replacing the old one already registered for location updates. Since a system service will most definitely outlive any activity, the LocationManager will still hold a reference to the previous activity, making it impossible for the garbage collector to reclaim the resources still tied to that particular activity, resulting in memory being leaked. Repeated rotation of the device will then cause non-reclaimable activities to fill up the memory, ultimately leading to an OutOfMemoryException.

But in order to fix a memory leak, we first have to be able to find it. Luckily Android Studio has a built in tool called Android Monitor we can use to observe memory usage among other things. All we really have to do is open the Android Monitor and go to the Monitors tab to see how much memory is used and allocated in real time.

The Android Monitor in Android Studio 2.0

Any interactions causing resource allocation will be reflected here, making it an ideal place for keeping track of your application’s resource usage. In order to find our memory leak, we need to know what the memory contains at a point in time when we suspect that memory has been leaked. For this particular example, all we have to do is start our application, rotate the device once and then invoke the Dump Java Heap action (next to Memory, the third icon from the left). This will generate a hprof file, which contains a memory snapshot at the time we invoked the action. After a couple of seconds, Android Studio automatically opens up the file, giving us a neat visual representation of the memory for easy analysis.

I will not go into depth about how to navigate the huge memory heap. Instead I’ll direct your attention to the Analyzer Tasks in the upper right corner of the screenshot below. All you have to do to detect the memory leak introduced in the example above is to check Detect Leaked Activities and then press play to get the leaked activity to show up under Analysis Results.