Android Out of Memory Exception & Paused Activities - android

I'm currently working on an android app with several activities. Most of the time, the app works fine, but from time to time an Out of Memory Exception occurs. (usually when trying to load the large background image for the next activity)
I couldn't find any obvious memory leaks, so I created a heap dump when the exception occurred (like described here) and tried to analyse it with MAT.
I haven't done something like this before, so I wasn't sure what exactly I should be looking for. I started clicking through the larger byte objects and the second one seems to be a Bitmap belonging to an ImageButton:
The Path to GC roots shows me an com.android.internal.policy.impl.PhoneWindow instance:
The thing is, the only ImageButton in my whole application is in my launch activity and between that launch activity and the crashing activity are at least 2 more activities.
So why is this image still in the heap??
The ImageButton is simply defined in the layout xml file using the android:src attribute, nothing is done via Code there. There are also a lot of other smaller objects from earlier activities in the heap.
I also wrote a little HelloWorld application and took a look in the heap dump of it and it seems, that android keeps the objects of previous activities in the heap. If this is the case, then an Out of Memory Exception has to be thrown some day, so I guess something must be wrong on my analysis :/

You might want to look at Bitmap managing in the developer's documentation.
In particular: a bitmap is kept in memory as long as a reference exists to it. So, if you absolutely have to use large bitmaps for your buttons (as you are describing) you might be do better by loading it manually and using recycle as soon as your Activity disappears from sight.

Okay, I just found this and realized, that stopped activities (and their objects) are NOT destroyed as long they are on the back stack. Even not if the active one needs more memory.
With this knowledge it is obvious why these objects like that ImageButton are still in the heap.
I still have to figure out the best way to release these resources, but I guess this strongly depends on the application itself and is hard to answer in general.

Related

MemoryLeak or not?

I experienced an OutOfMemory on my app and after some memory analyzing I got the following dominator tree. The first 4 instances are Activities that I started and directly closed. Since they hold a lot of views, the amount of memory that isn't garbage collected is huge.
If I then look into the path to GC for one of these elements I get the following:
The problem is that I don't know where these two references are coming from. I stripped the whole Activity to just have an onCreate/onDestroy, but I'm still getting these references. Does anybody know how to get rid of it so that the Activities can be garbage collected? Or is it a normal Android behavior and they will just disappear over time (which I doubt because I got the OutOfMemory)?
Thanks in advance for your help!

What can I do to avoid memory leaks in my Android app?

My android app is taking more and more memory over time. I took a heap dump and analyzed it with MAT.
Here's the main leak suspect :
So it seems like one of my activities isn't cleared from memory after I quit the app (with back button) then when I restart the app a new instance is created and fills in the memory.
Now if they're PhantomReferences why the memory isn't cleared after a while or when I quit the app? The memory is never cleared even when I use other app etc. The only way to completely close the app is to use a task manager to manually kill the app.
What can I do to avoid this anarchic memory consumption ?
EDIT:
I found the problem!
Each activity was setting up a CustomExceptionHandler with Thread.setDefaultUncaughtExceptionHandler() and that CustomExceptionHandler was keeping a reference to the context. So I got rid of the context reference and I 'nulled' the DefaultUncaughtExceptionHandler in the onDestroy() method. That's really better now!
I would use the dominator tree functionality of MAT to find out what is above those references, this may give you an idea of which Activity is the culprit.
Make sure you haven't passed a Context anywhere and held a reference to it, this is a classic android memory leak and it's really easy to do!
Although some static analysis tools frown on this, in the onDestroy() methods of your Activity you can null all your local variables (except primitives), it helps to nudge the garbage collector sometimes and can make for an easier to analyse heap dump in MAT.
Some generic approaches to reduce size of the app what I generally follow is this :
Call finish() below passing an Intent to next activity, this will avoid piling up of stack and helps in gc(garbage collection)
If you are not using shared preferences to save data, flush them at exit by calling System.exit()
If you find any drawable images/layout xmls/java classes which you are not using in your final program, ensure you remove them from the project
Images have to be .png since JPEG images take lot of memory.
In case of using database(sqlite, internal database etc), a better approach would be using "try/catch/finally" blocks, In try you open the db, in finally you close it, which will avoid memory leaks caused because of not closing cursors or databases.
Use AsyncTask instead of threads. in onPostExecute()function, close the progress dialogs if any.

Google Maps API causing memory leaks?

I just started using the Eclipse Memory Analyzer to try to solve a memory leak in my activity that extends MapActivity, but I am not sure if I understand its output correctly. In order to analyze the leak I started the activity and rotate the screen a couple of times and then I took a heap dump and opened it. The first thing I did was opening the Histogram view and look for my activity (called ChangeLocationActivity). This looks indeed like a memory leak, since there are three instances of the same Activity. So I got the list of objects with incoming references, then got the "Path to GC Roots" excluding weak references for all the three instances. This is the path of the first instance, this for the second instance (that custom MyLocationOverlay is a really simple class created to bypass a bug on some Motorola devices and it doesn't anything special apart from catching an Exception in drawMyLocation()) and finally this is the one for the third instance, which looks like the one currently shown.
As I said before I am not sure if I understand these results correctly (the Eclipse Memory Analyzer is really powerful but quite complex) but from what I can tell it looks like what's causing the memory leak is something related to the Google Maps library. Can anyone tell me if I am right or if I'm just not understanding these results?
Select all the activities and use "Merge Shortest Paths to GC Roots".
Post the result here.
Your second Activity seems to be alive because you registered an EventListener.
"Merge Shortest Paths to GC Roots" is one of the more important commands in MAT. It shows to all the pathes for objects to roots but merges them and therefore allows you to analyze which objects are still alive because they share the same pathes. From your screenshot (please expand the 3 subtrees) it seems your 3 activties are hold be 3 root objects. It is typical for leaks that the share some common objects along their merged root paths. Typically from what I've seen in your case you have more than one reason for the leak, because each activity is hold by a different root object. I would recommend to try to get as many activities to be leaked as possible by repeating the test.
Regards,
Markus

Android: Bitmap memory out

I knw this is one of the most discussed question but I couldn't figure out my way with the questions available here.
I'm decoding the bitmap as below
BitmapFactory.decodeFile(sdCardPath);
While executing above line randomly system running out of memory. This is not happening always . For example if I try to decode same image 3 times, it might go out of memory 3rd time or even 4th time. This error observed randomly.
How to solve this issue??
Thanks for your time in advance
First, if this is a bitmap that you are referencing from your assets, I would recommend moving it to your res/drawables folder, and access it as a drawable. If this is not the case, you are making too many references to this image without, as #VargaPeter pointed out, garbage collecting. The best way to garbage collect when using multiple bitmaps is to call recycle(), however System.gc() is often used as well (though in practice, you should use recycle(). If you are still having problems, you must either (a) allocate more space using the Android NDK (discouraged), or (b) use a smaller bitmap image (recommended). I know for certain there are posts discussing option b in several places on this site, as I had this same problem once before.
The Bitmap that you get back probably isn't garbage-collected because of a lingering reference.. Try to use the same reference if the app's design allows, or reusing a small number or references...

Android App - Can we Reuse Images in the Run time?

We have an Android application that throws out of memory error on Android 1.6. It is working fine on 2.0 onwards. We are trying to cut down on the runtime memory usage at this point.
We were thinking of reusing images – such as the background image of each screen. Is it possible to load the background image once in the memory at the time of app launch and reuse this cached copy in each screen rather than each screen loading the same background image increasing the overall footprint in the RAM?
We understand that there many other ways and best practices around runtime memory usage. But at this point, we just wanted to know whether this “image reuse” approach is really feasible?
If yes, how can we do this? Will it at all save any memory or the Android OS will still create multiple copies of the same asset for each screen not giving any benefit from the memory perspective?
Thank you very much for your time in reading my post.
If that background image is loaded as a Drawable from a Resource, it's bitmap data is already shared between all Drawables created that way. So no, it probably wouldn't benefit you in your particular case.
Yes you can reuse images.
It is usually done for ListViews where each row contains the same image.
In this case, you can get the Bitmap once in the constructor of your adapter, and reuse it in the getView() method, so you don't have to load it for each row. This trick is presented here
In your case, you could load your background bitmap in the onCreate() method of your main activity, save it as a public static attribute and then re-use it in all your activities.
But I think it won't make that much of a difference and surcharge the code for nothing.
As you are working on tweaking your UI, I suggest you watch the 2009 Google I/O Presentation by Romain Guy, if you did not see it yet. It shows a lot of useful tricks for boosting an UI's performances, especially when it comes to Bitmap manipulation.

Categories

Resources