Alright, please raise your hands if you have seen this error showing up before? Or have you detected that your application is acting weird? Weird as in strange application crashes, Severe performance degradation when the application is continuously running for a long time?
If this sounds familiar, there is a high chance that memory leaking is already happening in your app.
1. What is MEMORY LEAK?
You know, in Java, Objects are saved in a memory area called the heap. As it sounds, in heap, we can store heaps of objects there though it sometimes increases and reduces in size. Unfortunately, this heap has a limited space and once it reaches the limit, you will get to see OutOfMemoryError error message.
Useful article about OOM Error
Q: Then how can we clean the unnecessary memory?
A: Normally, there is a thing called GC(Garbage Collector)in Java that is periodically taking care of all the unused objects in memory.
GC: the built-in Garbage Collector (or GC for short). The GC implicitly takes care of allocating and freeing up memory and thus is capable of handling the majority of the memory leak issues.
Q: If Garbage collector can free up memory, why does this memory leak happen?
A: Let's have a look at the picture for better understanding!
Basically, When Garbage collector is freeing up the memory that is not being used, it checks that based on the fact that whether the object is unreferenced or referenced. If this object is identified as unreferenced object then GC will consider this as unused object to clean up and will get on with it.
However, in real world, it is most likely that we have objects that are not being used really but still being referenced with other objects in the app. As expected, Garbage collector is obviously not capable of identifying those troublesome objects and as a result, those objects will stay not being properly handled, using up the amount of memory available for the app, which causes unexpected results.
I mean, it is pretty much like, when we clean our room or when we move out, in a situation where we have to get rid of all the stuff that we are not actually using to start fresh, there are always some stuff that bug us all the time, right?
If you are much of a collector, you would understand what I am saying. There is no doubt that you are not using them and haven't been using them for a long time but then there is always some references to it that makes you hesitate to remove them but if you keep keeping them in your room, these will take up the most of the space and you will need to somehow remove them.
2. What could cause MEMORY LEAK?
In any application, memory leaks can happen for numerous reasons. There are 3 most common cases.
1. Heavy use of static
The first scenario that can cause a potential memory leak is heavy use of static variables.
In Java, static fields have a life that usually matches the entire lifetime of the running application. Unless we set it NULL when we are done using, there is a possibility that these variable stay in memory and be a potential cause of leaks.
Bitmap objects are quite heavy in general, and if they are dealt with improperly, they can lead to significant memory leaks that eventually crash your app due to OutOfMemoryError. Most of the time, theses objects have something to do with images and if they are not handled in framework, it is recommended to use recycle() after using them.
Another common reason for memory leaks is the misuse of the Context instances.
Context might sound familiar since is is commonly used as an abstract class that is extended to provide class' functionalities.
However, there are two important types of contexts which are activity-level context and app-level context. If activity Context is used in a wrong place, this reference can be kept to entire activity and be a potential leak.
Here is some article about types of Contexts in Android
3. How do we detect MEMORY LEAK?
If you are working on a big scale of application code written by someone else long ago and somehow you should figure out why this memory leak is happening, there are 2 amazing, recommended ways to do that.
In Android docs, profiler is defined as below:
The Memory Profiler is a component in the Android Profiler that helps you identify memory leaks and memory churn that can lead to stutter, freezes, and even app crashes. It shows a realtime graph of your app's memory use and lets you capture a heap dump, force garbage collections, and track memory allocations.
So let's say that your device or emulator is connected to the android studio, and you open the profiler(normally View > Tool Windows > Profiler), and then let the application run for a bit.
Then you will see something similar as this picture.
You can carefully have a look into the graph and probably set the timing of the memory capture if needed to find out when the memory leak is happening, reading through the objects listed and identify whether these objects are supposed to be here or removed. If they exist when they are not supposed to be, this is where memory leak is detected and start thinking about optimizing the class.
This profiler helps analysing memory data and provides so much filter and information in depth.
For example, it provides,
- What types of objects were allocated and how much space they use.
- The stack trace of each allocation, including in which thread.
- When the objects were deallocated (only when using a device with Android 8.0 or higher).
For more information, click Here to read documentations on profiler.
Profiler provides very useful insight and analysis on memory leak, being connected to devices and allow us to be able to simulate the scenario and play with those. However, Here is one more thing you might want to have a look. LeakCanary.
LeakCanary is an Open Source Java library to detect memory leaks in your debug builds. The biggest advantage of using LeakCanary is that LeakCanary will automatically show a notification when an activity memory leak is detected in your debug build.
To sum up, as the size of the application is getting bigger, the harder it gets to troubleshoot app crashes and figure out the causes. In a same sense, since memory heap is not something clearly visible for us, it is really complicated to know exactly where and when the memory leak is happening. Using profiler and library such as LeakCanary, we can at least diagnose the problem with some meaningful data and analysis derived to start the troubleshooting on a right point.