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!
Related
I am trying to understand how to identify and solve memory leaks.
I know how to deal with general memory leak issues. Leaked activities, inner classes etc. They are usually quite easy to identify. By dumping the heap and look for references.
Right now i am stuck with something probably very simple. Some very small object are stuck in the heap and i just cannot find any references to it in the heap explorer. See image below.
As you can see there is a MatchOddsAdapterStickyHeader instance and an array containing these instances.
My question is why these objects are still in the heap.?
The MatchOddsAdapterStickyHeader[] instance only contains references to a single MatchOddsAdapterStickyHeader instance. And each single MatchOddsAdapterStickyHeader only have a string. I just don't understand why GC did not clean up this objects. Both object have no references to any alive object. And yes i forced GC. makes no difference.
I know its only a few bytes. And it doesn't really give a problem in my app, but still i want to have a 100% memory leak free app if possible.
I ran MAT on my application to see if I can reduce memory leaks and `OutOfMemoryException's that are happening to my users.
I saw in the histogram that was generated by the tool that one of my activities wasn't cleared from memory even though I called finish and created no cyclic references that I was aware of. so I looked through all the incoming references excluding all soft/weak references and saw that there's an EditText that has no name and that I haven't put in the activity.
attached is a screenshot of the report.
please help me understand how to plug this leak.
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.
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.
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