Android multiple activity instances in memory snapshot on screen rotation change - android

I created a simple Blank Activity (MainActivity class) in Android Studio and ran it on my Samsung phone. I rotated the screen several times from portrait to landscape mode. I took a memory snapshot and discovered that there were several instances of my Activity (MainActivity class) in the snapshot. Why are there multiple instances of the MainActivity in the memory profile? I don't have any code that holds any references to the Main Activity like talked about AsyncTasks or Threads.
I have read the http://developer.android.com/guide/topics/resources/runtime-changes.html documentation. But I am curious if the multiple instances are normal operation and are gc'ed eventually to just one Activity instance.

The HPROF viewer shows all objects resident in memory, even if the object is not reachable from any GC roots. You can tell if an Activity is leaked by inspecting the "Distance to GC Root" column of the object. If it's not reachable, it will be blank, and will be collected, at the very least, when a full GC sweep is performed. If it has a number in that column, then you can inspect the object itself to find what's holding a reference to it.
If you find a leak when it's not intended, it'd be great if you reply with what's causing the leak.

Related

Distinguishing between a memory leak and normal memory usage

I am creating an Android app, and I've only just recently begun to examine the memory usage.
My app consists of a main activity and two fragments within (Fragment A holds a recyclerview with images, Fragment B holds an image and some text boxes).
I've noticed that when I start the app, my memory allocation is at roughly 20MB. By scrolling up and down on the recyclerview in Fragment A (not loading any new data) I can make the memory usage increase nonstop (until garbage collection).
Also, if I go from fragment A to fragment B back and forth, I can make the memory allocation increase nonstop (until garbage collection). 20 -> 23 -> 29, .. etc. Until it gets to 60+ and gets garbage collected.
If I start the app at roughly 23MB allocated, and do some scrolling and moving back and forth between fragments, my memory usage might be somewhere between 40 and 60+ MB.
When I use Android Studio to garbage collect multiple times in a row, I can bring it back down but not all the way to 23 (usually to 30ish).
Is this a memory leak since I'm unable to garbage collect 100% of the memory I started out with?
No, strictly speaking you can't have that kind of memory leak in java since it is garbage collected.
You'll get "leaks" in java if you are keeping a reference to something you no longer use (I.E. a big list or something that you never remove from). But keep in mind that these can always be fixed by being sure to discard references to things you don't need to keep around (removing things from lists/sets/maps, closing files ... etc). The persistent memory that you are looking at is probably from some static variables since those are bound to the classes.

Android clear the back stack if out of memory

When running on Huawei G300 with Gingerbread, my app crashes after 5 minutes or so of usage during setContentView() as it runs out of memory.
Each individual page doesn't use much memory, but from some research it seems the memory accumulates in the back stack.
Following advice here, I've replaced all my calls to startActivity with a utility function that also calls finish().
Android: Clear the back stack
This works; but there is no more back stack - the back button immediately quits the app, which isn't what I wanted.
Is there a way to only finish() the applications when I actually do run out of memory, and is that a reasonable approach to take?
You should search for memory leaks. A good tool for that is MAT if you use eclipse. MAT is not that hard to handle and you can get quickly some very valuable information.
One of the most common mistakes I have seen on Android is to keep a reference on a context that is dead. For instance, having a singleton holding a reference on one of the activities you created. There is no real reason for an app to crash the memory if it is well coded.
The Android Activity Manager was designed to manage this exact problem. The OS is designed to kill activities in the background and then restore them using onSaveInstanceState and onRestoreInstanceState.
The fact that your app is accumulating memory usage over time indicates to me that you may have a Context leak somewhere (a static reference to a view, adapter, etc. that has a reference to a Context), or that you have a caching mechanism that's not adjusting to your memory heap, or some other situation that's causing the out of memory.
I highly doubt that it's the Activities in the Back Stack causing the Out of Memory.
Here's a great guide on tracking down memory leaks on Android:
http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html
Memory is a very tricky subject in Android.
Every app gets a heap memory limit depending on the device. This heap memory is the dalvik memory plus the native memory, and you can see it as the total column in the dumpsys meminfo results. The dalvik memory deals with everything except with the bitmaps, that are allocated in the native memory (this is true for Android versions before Honeycomb).
Having said that I can only answer to some of your questions:
As far as I know, Android will always allocate memory for Bitmaps, even if they are the same. Therefore, in your case, every activity allocates memory for your background.
I don't know if its better to work with themes, you'll have to try that.
On one hand, activities are not reclaimed while the device has enough memory to deal with the next activity. Every activity is pushed to a pile from where it is recovered when you pressed the back button. In case Android needs more memory it removes one activity from the pile deallocating its memory (going back to question number one, maybe this is the reason for not sharing memory). On the other hand, you can set the activities launchMode to change this behaviour (have a look here).
I think MAT doesn't show native memory data. Use dumpsys meminfo's native column to see how much allocated memory for Bitmaps you have.
I have had hard times dealing with OutOfMemory problems myself. Now I have a much more clear idea of how it works and I am able to work with large files without running out of memory. I would highly recommend these two resources that helped me a lot:

First instance of activity never gets garbage collected?

I'm investigating whether my Android activity has a memory leak using the Eclipse Memory Analyzer Tool (MAT). If the activity has a leak, I would expect dead instances to be hanging around on the heap, not getting garbage collected. To check this, I repeatedly start and stop (by pressing the Back button) the activity, and then inspect heap dumps using the MAT.
But I'm observing some strange behaviour that I cannot explain: the very first instance of the activity (started after a having done a force close) never gets garbage collected. However, subsequent instances do. I know this from inspection using the MAT tool: no matter how many times the activity is started and stopped, the MAT tool always shows two instances on the heap. The first instance belongs to the very first time the activity was started, while the second instance belongs to the most recently run activity.
Any idea as to what may be happening, and whether I should be worried about this wrt. memory leaks? Suggestions are much appreciated.
Just to close: seems that there are known issues with memory leaks in MapActivity subclasses. See e.g. code.google.com/p/android/issues/detail?id=2181. Haven't found a fix that works for me yet.

android GoogleMaps memory leaks (?)

I'm working on a project dealing with map activities.
I was running a testing app consisting of a single activity, MaptestActivity, that extends MapActivity and does nothing else. I rotated the device more than ten times and I analyzed the heap dump with MAT. I noticed the existence of two instances of the main activity hanging around (a leak?). I re-tested the app with the same activity extending only Activity: the dump showed only one instance being kept by the system, the current one.
I'm attaching the screenshots of both cases. I'm not much into MAT, maybe I'm just misunderstanding the reults and everything works fine. Could you please shed some light on it?
With memory leak
Without memory leak
If you still have two activities in memory after rotating the device then you do have a memory leak. You can use MAT to see what is preventing that activity from being garbage collected by using the Histogram. Search on the class name to find it. Then right click on it and select list objects/with incoming references. That will list each occurrence of this object in memory. Right click on one of these objects and select Path to GC roots/exclude weak references. Now you should be able to see a hierarchy of objects, of which something is not getting cleaned up completely after the activity's onDestroy has finished. Things like hard references to a static context will cause this. To resolve some of our memory issues we've had to do things like use weakReferences where appropriate, and clean things up in onDestroy (like setting listeners to null).
Normally if your activities are not holding onto large objects like bitmaps you can "get away" with memory leaks since it would mean lots of app usage before you exceed the device's application heap size. But if say all of your activities hold onto a large bitmap, then leaking activities become much more of a big deal.
This is a good video: Memory Management for Android Apps
And a good article: Avoiding Memory Leaks
add the below line in for your activity in your manifeast file
android:configChanges="keyboardHidden|orientation"

Objects are still in memory after activity is destroyed

My activity keeps a certain number of references to preview images from the camera in a Map object. This takes a lot of memory. I'm monitoring the memory usage using:
Runtime runtime = Runtime.getRuntime();
long allocated = runtime.totalMemory();
long free = runtime.freeMemory();
long used = allocated - free;
When I kill my app (back key), the activity is destroyed. When I start my app again, I can see that the memory was not cleared. The "used" figure starts at the same value and then goes up as new frames arrive.
When I look at the "dominator_tree" after I "Dump HPROF", I can see two instances of my activity, both taking a lot of memory.
When I override onDestroy() and I clear() the preview frames map object, this doesn't seem to happen.
I'm probably missing something here but I thought all memory should be deallocated after my activity is destroyed (after the garbage collection process), why do I have to manually clear() the map? Other objects I create don't seem to require this.
I tried setting android:launchMode="singleInstance" but this doesn't seem to have any affect.
Thanks!
in order to understand what's happening, in the dominator tree, on your activity click with the right button, look for PATH to GC ROOT and select the option that exclude weak/soft/phantom references. That would give you an idea why the system could not destroy your activity (if you are leaking something or what else)
Garbage collector will run as needed, at an indeterminate time chosen by the runtime. GC may or may not run when your application exists.
However, if your objects still stay in memory after GC is run it means you are leaking memory. You can check the logs in logcat while debugging to see when it is run.
For a good tutorial how to detecting and fixing leaks check Android Memory Management Video from Google.

Categories

Resources