Android Running apps memory usage - android

What is the difference between the heap usage (Allocated) we can see in the Elipse Memory Analysis Tool (in the DDMS view) and the memory usage size for the same App shown here on the Android device?:
Settings->Apps->Running
Even though I aggressively tried to preserve memory by making objects null as soon as they weren't needed, the latter number (memory usage size on Running apps screen) only kept increasing and my app finally crashed due to OutOfMemoryError. However, the former showed me that I was well within a reasonable size. I was also calling System.gc() a lot. Is there a difference between the two? Why the discrepancy? Any ideas on how I can solve this problem?

The biggest difference between the two that I know of is the scope of garbage collection.
Normal garbage collection, including System.gc(), collects a bit of garbage, then stops. It is not a complete sweep of the heap to get rid of everything. That is to try to minimize the CPU impact of garbage collection.
The heap dump prepared for MAT, though, effectively a complete GC.
Your symptoms suggest that you are allocating memory faster than GC can reclaim it. The primary solution for this is to try to allocate less memory, or allocate it less frequently. For example, where possible, reuse objects, bitmap buffers, and the like, instead of trying to let GC clean the old stuff and allocating new stuff as you go.

It sounds like you have a memory leak somewhere in your application if the memory is never released. This means that somewhere you are maintaining a strong reference to a large object which is being recreated (like an Activity or Bitmap) which is why calling System.gc() is making no difference.
I suggest watching the following on memory management in android from google IO 2011. It lets you know how to use the eclipse memory analyser tool which is incredibly useful for debugging this sort of error

Related

After app startup, 70% of the memory is occupied by FinalizerReference

I was investigating the memory consumption of my android app. Immediately after app startup, I clicked 'Dump Java Heap' and the first class on the list is FinalizerReference (java.lang.ref). It has over 800 instances and consume more than 70% of the total memory comsumption.
I understand it is for garbage collection. Unlikely it is because of memory leak since it was captured right after app startup without switching to another view. I did not do any heavy processing during startup, apart from reading something from the shared preference.
Possible Memory leak through FinalizerReference
From this post, I tried to look on the referent field of the FinalizerReference, but it appears to be something that beyond my understanding e.g. Matrix, Canvas, Render Node. It sounds like UI components for me.
Here is my question:
Is there any way/tool for me to further debug the root cause of memory comsumption.
Is this something that I need to worry, or it is just the normal behavior of android memory management.
A better tool would be useful, but only because it should show that the reported Retained Size of ~33 MB for FinalizerReference is not real memory consumption, just massive multiple counting of the same small amount of memory by the Memory Profiler. The Shallow Size of ~28 kB is important, but negligible. The way I investigated this (using Memory Profiler) is detailed in my answer to my own similar question.
You should not worry about FinalizerReference, at least not based on what you show here. You may need to worry about Memory Profiler, due to the meaningless Retained Size it reports for this class. I regard its calculation as a bug, and I filed this issue.

Is this memory leakage

I am planning to hunt any memory leak in my Android App. After searching through different blogs, it seems like MAT is a good tool for that.
Before proceeding further, I just want to make something clear. When I check allocated heap memory in memory monitor tab of android studio, i can see the allocated memory increases by ~1 MB (from 16MB of initial allocation) each time I rotate my device. This, most probably suggests some leaks.
However in the process, at any stage, whenever I click on Garbage Collection button in memory minitor window to force GC, the allocated memory comes down to near the initial stage 16MB+ (sometimes requires 2 back to back click when allocated memory expands beyond 30 MB).
My question is, does this behavior suggests that I don't have any leaks due to strong references? If GC can collect those extra chunks, how important is that to check the issue?

Android Heap Fragmentation Strategy?

I have an OpenGL Android app that uses a considerable amount of memory to set up a complex scene and this clearly causes significant heap fragmentation. Even though there are no memory leaks it is impossible to destroy and create the app without it running out of memory due to fragmentation. (Fragmentation is definitely the problem, not leaks)
This causes a major problem since Android has a habit of destroying and creating activities on the same VM/heap which obviously causes the activity to crash. As a strategy to counter this I have used the following technique:
#Override
protected void onStop() {
super.onStop();
if(isFinishing()) {
System.runFinalizersOnExit(true);
System.exit(0);
}
}
This ensures that when the activity is finishing it causes a complete VM shutdown and therefore next time the activity is started it gets a fresh unfragmented heap.
Note: I realise that this is not the "Android way" but given that the garbage collector is non-compacting it is impossible to continuously re-use the heap.
This techinque does actually work in general, however it doesn't work when the activity is destroyed in a non-finishing mode and then re-created.
Has anyone got any good suggestions about how to handle the degredation of the heap?
Further note: Reducing memory consumption is not really an option either. The activity doesn't actually use that much memory, but the heap (and native heap) seem to get easily fragmented, probably due to some large'ish memory chunks
Fragmentation is almost always a consequence of an ill conditioned allocation pattern. Large objects are frequently created and destroyed. In conjunction with smaller objects may persisting (or a least having a different lifetime) - holes in the heap are created.
The only working fragmentation prevention in such scenarios is: prevent the specific allocation pattern. This can often be done by pooling the large objects. If successfull, the application will thankfully acknowledge this with a much better execution speed as well.
#edit: yet more specific to your question: if the heap after a restart of the application is yet not empty, so what is there to remain on the heap? You confirmed that its not a problem of a memory leak, but this is, what it seems. Since you are using OpenGL - could it possibly be, some native wrappers have survived, because the OpenGL ressources have not properly been disposed?

Android, I see heap growing, but I want it to stop

I see my heap growing and I know it will eventually crash on any device since it just keeps growing.
Grow heap (frag case)
is seen throughout the logs
on my phone it will crash the app at 32mb used. Other phones will of course be 16mb, if there are any with that few resources that run android 2.2
Now, I am using recycle() on my bitmaps, setting things to null, popping items from complex data structures, and using System.gc() to invoke garbage collection, throughout the app
but, the heap still grows and its a problem... eventually
How do I just force the app to dump resources so that it can continue functioning.
it is usually always the "bitmap vm budget" exceeding, but I am feeling more and more that I just don't have access to the "clear bitmap vm" command
i had also struggled a lot with this issue. there are many a things you can do.
you can call recycle on each bitmap and set them to null.(bitmap.recycle() with relaese all the memory used by this bitmap but does not nullify the bitmap object ).
you can also unbind the drawables associated with layouts as specified in this link.
you can convert your hashmaps to WeakHashmaps. so that its memory would get relaesed when system runs low on memory.
you can resize all your bitmaps. have a look at this link..
you can override onLowMemory() method in activity which gets a call when entire system runs low on memory. you can release few resources there.
you can make your objects SoftReference or Weakreference, so that they get released in low memory condition.
But the real fact is that, all this can DELAY your out of memory issue/crash, but can not eliminate it because thing is that you must be leaking your activity context or memory somewhere.

Using caching to improve scrolling performance in an android ListView with images

I'm currently using a filesystem cache to cache my images as I download them from the server. I have a ListView that contains custom views, each of which retrieves its image from the filesystem when getView() is called.
To improve performance, I implemented a java.util.WeakHashMap<String,Bitmap> that stores each of the bitmaps by a unique key. This allows me to tuck the images into the hashmap as they're downloaded, and then retrieve them directly from memory to populate my listview. This avoids a file I/O operation and results in a much smoother scrolling experience.
The idea is that as the OS runs low on memory, it will clean out the WeakHashMap to free up memory.
However, this doesn't work on Android 2.3 or earlier. The problem is that bitmaps are not kept in the Java Heap, and are instead kept in native memory. This means that the JVM garbage collector has no idea how much memory those images are occupying, and thus never bothers to free them up when the OS is low on native memory, resulting in OutOfMemory errors when there's plenty of memory that can still be reclaimed.
This has been fixed in Android 3.0, since 3.0 stores bitmaps in JVM heap instead of native memory, but the question is how can I easily cache bitmaps on Android 2.3 and later without inadvertently causing unnecessary OutOfMemory exceptions?
You might try something like this: http://code.google.com/p/xlarge-demos/source/browse/trunk/PhotoAlbum/src/com/example/android/photoalbum/LruCache.java and explicitly recycle() your Bitmaps in the evicted step.
So the answer seems to be that there's a bug in the way the dalvik VM detects when it needs to do a GC pass. If you manually call System.gc() immediately before allocating memory for your bitmap, the OutOfMemory errors surprisingly go away.
if(Build.VERSION.SDK_INT < 12) {
Log.d("Running garbage collection for Bitmaps");
System.gc();
}
return BitmapFactory.decodeStream(is);
Obviously, the VM should be doing this GC automatically before it throws an OutOfMemory, but it does not appear to do so.
So, even though Bitmap memory is allocated on the native heap in earlier versions of Android, this memory is still charged against your process, its just harder to see, this is why you might get an OOM Exception. However, your basic analysis is correct though. The problem is that the native code doesn't really have a good idea when it can deallocate memory for Bitmaps, which is why its recommended that developers all Bitmap.recycle(), since this essentially tells native code that its okay to free the memory. Likely when items are removed from the WeakHashMap, this isn't being called.
However, empirically I'd built a similar system using a HashMap<String, SoftReference<Bitmap>> and Bitmap memory was properly freed. I'll note though that I think this solution became less effective starting in Android 2.3 because of changes to the garbage collector, although I'd need to go back and verify this remembrance.
In the end I guess the answer is that I don't know of a good answer to this question that doesn't use explicit management like the LruCache. It would be great to have a solution that uses SoftReferences or WeakReferences, but with the current way we do garbage collection I'm not sure this will work.

Categories

Resources