Memory leaks in Android are quite easy to create. The unsuspecting developer might be making a few memory leaks every days without realising. You probably haven’t noticed them yet or even know that they exist. Until you see an exception like this….
1
2
3
4
5
6
7
8
9
10
11
java
.
lang
.
OutOfMemoryError
:
Failed
to
allocate
a
4308492
byte
allocation
with
467872
free
bytes
and
456KB
until
OOM
at
dalvik
.
system
.
VMRuntime
.
newNonMovableArray
(
Native
Method
)
at
android
.
graphics
.
BitmapFactory
.
nativeDecodeAsset
(
Native
Method
)
at
android
.
graphics
.
BitmapFactory
.
decodeStream
(
BitmapFactory
.
java
:
609
)
at
android
.
graphics
.
BitmapFactory
.
decodeResourceStream
(
BitmapFactory
.
java
:
444
)
at
android
.
graphics
.
drawable
.
Drawable
.
createFromResourceStream
(
Drawable
.
java
:
988
)
at
android
.
content
.
res
.
Resources
.
loadDrawableForCookie
(
Resources
.
java
:
2580
)
at
android
.
content
.
res
.
Resources
.
loadDrawable
(
Resources
.
java
:
2487
)
at
android
.
content
.
res
.
Resources
.
getDrawable
(
Resources
.
java
:
814
)
at
android
.
content
.
res
.
Resources
.
getDrawable
(
Resources
.
java
:
767
)
at
com
.
nostra13
.
universalimageloader
.
core
.
DisplayImageOptions
.
getImageOnLoading
(
DisplayImageOptions
.
java
:
134
)
What? What does that even mean? Does it mean my bitmap is too large for the Android System?
Unfortunately, seeing this kind of Stack trace may be a bit deceiving. When you receive an OutOfMemoryError, it generally means, 9 times out of 10 that you have a memory leak. My first impressions of this stack trace left me confused and thinking that my bitmap was too large… Boy was I wrong.
What is a memory leak?
A failure in a program to release discarded memory, causing impaired performance or failure.
How is a memory leak caused in Android?
Memory leaks in Android are actually quite easy to make, which is probably part of the problem. The biggest issue is the Android Contextobject.
Every app has a global application context ( getApplicationContext()). Every activity is a subclass of Context , which stores information related to the current activity. More often than not, your memory leak will be associated with a leaked activity.
The unassuming developer would pass this context object around to the threads that need it. Make some static TextViews that hold reference to the activity. You know, things that make it work? *sarcasm intended, do not try those things at home*
The opposite of how things will work.
A big warning sign to lookout for is the ever increasing memory usage in your app, as depicted by Androids Memory Monitor:
Android Memory Monitor running with an app that has a memory leak
Android Memory Monitor after fixing the memory leak
As you can see, the first graph, the app is never able to really regain some of the memory used. It used up to about 300MB at one point before the OutOfMemoryError occurred. The second graph shows that the app is able to garbage collect, regain some memory and stays pretty consistent in its memory usage.
How do I avoid memory leaks?
Avoid passing Context objects further that your activity or fragment
NEVER EVER EVER make/store a Context or View in a static variable. This is the first sign of a memory leak.
1
2
private
static
TextView
textView
;
//DO NOT DO THIS
private
static
Context
context
;
//DO NOT DO THIS
Always unregister listeners in your onPause()/ onDestroy() methods. This includes Android listeners, to things such as Location services or display manager services and your own custom listeners.
Don’t store strong references to activities in your AsyncTasks or background threads. Your activity may get closed, but your AsyncTask will continue execution and hold onto that reference of your activity.
Use Context-application (getApplicationContext()) instead of Context from an activity if you can.
Try not to use non-static inner classes if you can avoid it. Storing reference to something like an Activity or View inside this can lead to memory leaks. Use WeakReference if you need to store reference to them.
How do I fix it?
Fixing memory leaks takes a bit of practise and lots of trial and error. Memory leaks can be very difficult to track down. Luckily there are a few tools that can help you identify a possible leak.
You can watch this video which shows how to obtain the HPROF file to use for analysis, or you can read the tutorial below describing how to do it.
Open Android Studio, open the Android Monitor tab.
Run your application, and select it from the list of available apps.
Do some actions in your app that lead you to a similar point. For me, it was selecting a new video, and playing it about 50 times. (I wrote a test for this